├── .github └── workflows │ ├── dry-run-publish.yml │ ├── mk.yml │ └── python-publish.yml ├── .gitignore ├── History.md ├── LICENSE ├── MANIFEST.in ├── Pipfile ├── Pipfile.lock ├── README.md ├── create_man ├── build.bat ├── requirements.txt └── test-website.py ├── docs ├── ActorBasedPattern.md ├── Entity Component System │ ├── A bit of theory.md │ └── ECS examples.md ├── GameTutorials │ ├── Breakout.md │ ├── Platformer.md │ ├── Roguelike.md │ └── img │ │ ├── breakoutend.png │ │ ├── breakoutmid.png │ │ ├── platformerSource │ │ ├── background.png │ │ ├── barry.png │ │ └── wall_small.png │ │ ├── rogueSource │ │ └── image.png │ │ └── screenshot.png ├── Other patterns │ ├── Event based programming.md │ └── MVC examples.md ├── Reference │ ├── Gamestates.md │ └── Using sprites.md ├── ShareYourGames.md ├── Showcase.md ├── flappybird-preview.png ├── image.en.fake ├── image.en.png ├── image.fr.fake ├── image.fr.png ├── images │ ├── ECSBlockDiagram.png │ ├── gallery1.png │ ├── gallery2.png │ ├── mediator.webp │ ├── mvc.jpg │ └── mvc1.ppm ├── index.md ├── kengi-palette-preview.png └── match3-preview.png ├── examples ├── astero │ ├── (astero)enter_start.png │ ├── (astero)explosion_002.wav │ ├── (astero)ndimensions-zik.ogg │ ├── (astero)rock.png │ └── astero_run.py ├── blokumanBundle │ ├── cartridge │ │ ├── TetColors.py │ │ ├── TetPiece.py │ │ ├── TitleView.py │ │ ├── __init__.py │ │ ├── blokuman-bt_rouge.png │ │ ├── coinhigh.wav │ │ ├── coinlow.wav │ │ ├── crumble.wav │ │ ├── defs.py │ │ ├── ev_types.py │ │ ├── fonts_n_colors.py │ │ ├── gamedef.py │ │ ├── glvars.py │ │ ├── labels.py │ │ ├── loctexts.py │ │ ├── menu_state.py │ │ ├── metadat.json │ │ ├── pimodules.py │ │ ├── puzzle_compo.py │ │ ├── puzzle_state.py │ │ └── util.py │ ├── vm.py │ └── vmslateL.py ├── bubbleshooter │ ├── __init__.py │ └── bubble.py ├── capello-ft │ ├── LICENSE.txt │ ├── capello-ft.json │ ├── capello-ft.png │ ├── capello.py │ └── datapacker.py ├── conversation │ └── main.py ├── cutscene_exp │ ├── component_camera.py │ ├── component_text.py │ ├── core_component.py │ ├── cutscene.py │ ├── gamedefs.py │ ├── gamma.py │ ├── gutils.py │ ├── manager_scene.py │ ├── rectangle.py │ ├── renderable.py │ ├── renderer.py │ ├── scene.py │ ├── shared.py │ ├── systems.py │ ├── test_cutscene.py │ ├── vita_00.png │ ├── vita_01.png │ ├── vita_02.png │ └── vita_03.png ├── ecs_naif │ ├── demo_entities.py │ ├── demo_systems.py │ ├── en_run.py │ └── topdown-shooter-spritesheet.png ├── gamepad_testing │ └── gamepad.py ├── immortalBundle │ ├── __init__.py │ ├── cartridge │ │ ├── __init__.py │ │ ├── bg.png │ │ ├── defeat.png │ │ ├── gamedef.py │ │ ├── immortal-magic.wav │ │ ├── immortal-music.mp3 │ │ ├── immortal-sword.wav │ │ ├── immortal-turok.ttf │ │ ├── metadat.json │ │ ├── pimodules.py │ │ ├── sorc-spritesheet.json │ │ ├── sorc-spritesheet.png │ │ ├── victory.png │ │ ├── warrior-spritesheet.json │ │ └── warrior-spritesheet.png │ ├── vm.py │ └── vmslateL.py ├── isometric0 │ ├── isometric-keyb-movement.py │ └── xassets │ │ ├── floor-tile.png │ │ ├── half-floor-tile.png │ │ ├── spritesheet.png │ │ ├── sync-tileset.json │ │ ├── sync-tileset.tsx │ │ ├── sys_icon.png │ │ ├── test_map.json │ │ ├── test_map.tmx │ │ ├── test_map2.tmj │ │ └── test_map2.tmx ├── platformer0 │ ├── assets │ │ ├── enemy.png │ │ ├── info-asset-license.txt │ │ ├── missile.png │ │ ├── player-left.png │ │ ├── player-right.png │ │ ├── tiledbackground.png │ │ └── tilemap.png │ ├── level.tmx │ ├── run_platformer0.py │ ├── sprites.py │ └── tiles.tsx ├── poker_uth │ ├── play_poker.py │ ├── pokerbundle │ │ ├── __init__.py │ │ └── common.py │ └── user_assets │ │ ├── capello-ft.json │ │ ├── capello-ft.png │ │ ├── overlay0.png │ │ ├── pokerbackground3.png │ │ ├── pokerchips.json │ │ ├── pokerchips.png │ │ ├── pxart-french-cards.json │ │ └── pxart-french-cards.png ├── protoAsteroBundle │ ├── _xx_rungame.py │ ├── dummylib.py │ ├── dummylib2.py │ ├── geometry.py │ ├── ship.py │ ├── shooter.py │ ├── soundManager.py │ ├── stage.py │ └── vectorsprites.py ├── survival │ ├── assets │ │ ├── (zombie)bonus.png │ │ ├── (zombie)bullet.png │ │ ├── (zombie)cell_tower.png │ │ ├── (zombie)comms_icon.png │ │ ├── (zombie)health_icon.png │ │ ├── (zombie)hitman_gun.png │ │ ├── (zombie)landmine.png │ │ ├── (zombie)light_350_med.png │ │ ├── (zombie)manBlue_gun.png │ │ ├── (zombie)mine_icon.png │ │ ├── (zombie)pistol.png │ │ ├── (zombie)pistol_ammo.png │ │ ├── (zombie)shotgun.png │ │ ├── (zombie)shotgun_ammo.png │ │ ├── (zombie)uzi.png │ │ ├── (zombie)uzi_ammo.png │ │ ├── (zombies)explosion.png │ │ ├── (zombies)tile_179.png │ │ ├── (zombies)whitePuff15.png │ │ ├── (zombies)whitePuff16.png │ │ ├── (zombies)whitePuff17.png │ │ ├── (zombies)whitePuff18.png │ │ ├── (zombies)xxORGxxexplosion.png │ │ ├── DemonSker-zyzD.ttf │ │ ├── blood-splatter1.png │ │ ├── blood-splatter2.png │ │ ├── blood-splatter3.png │ │ ├── blood-splatter4.png │ │ ├── icons.png │ │ ├── icons.svg │ │ ├── light_350_hard.png │ │ ├── light_350_soft.png │ │ ├── light_radius.png │ │ ├── maps │ │ │ └── level1.tmj │ │ ├── shotgun_ammo_icon.png │ │ ├── snd │ │ │ ├── 10.wav │ │ │ ├── 11.wav │ │ │ ├── 12.wav │ │ │ ├── 13.wav │ │ │ ├── 14.wav │ │ │ ├── 1beep.mp3 │ │ │ ├── 8.wav │ │ │ ├── 9.wav │ │ │ ├── City-of-the-Disturbed.ogg │ │ │ ├── ammo_pickup.ogg │ │ │ ├── brains2.wav │ │ │ ├── brains3.wav │ │ │ ├── chiptronic.wav │ │ │ ├── drop_sound.wav │ │ │ ├── empty_gun.wav │ │ │ ├── espionage.ogg │ │ │ ├── explo_basique.wav │ │ │ ├── gun_pickup.wav │ │ │ ├── item_pickup.ogg │ │ │ ├── level_start.wav │ │ │ ├── pistol.wav │ │ │ ├── short_explosion.ogg │ │ │ ├── shotgun.wav │ │ │ ├── splat-15.wav │ │ │ ├── uzi.wav │ │ │ ├── zombie-roar-1.wav │ │ │ ├── zombie-roar-2.wav │ │ │ ├── zombie-roar-3.wav │ │ │ ├── zombie-roar-4.wav │ │ │ ├── zombie-roar-5.wav │ │ │ ├── zombie-roar-6.wav │ │ │ ├── zombie-roar-7.wav │ │ │ └── zombie-roar-8.wav │ │ ├── spritesheet_tiles.png │ │ ├── zombie1_hold.png │ │ └── zombie2_hold.png │ ├── run_survival.py │ ├── sprites.py │ └── z_constants.py ├── survival_c │ ├── game.py │ ├── shared.py │ ├── systems.py │ └── topdown-shooter-spritesheet.png └── tmx_testing │ ├── level.tmx │ ├── main.py │ ├── tiledbackground.png │ ├── tilemap.png │ └── tiles.tsx ├── examples_basic ├── demo-a-kengi-straightf.py ├── demo-a-pygame.py ├── demo-ascii.py ├── demo-pathfinding.py ├── dummy-game-mvc.py ├── imgfont-creat-helper.py ├── min-example-gui.py ├── mixed_assets │ ├── alphbeta.ttf │ └── niobe_font.png ├── multistate-pyv-game.py ├── quick-breakout.py └── show_pal.py ├── mkdocs.yml ├── requirements.txt ├── runtime-req.txt ├── setup.py ├── shared.game.png ├── src ├── .gitignore ├── pyvcmdline │ ├── __init__.py │ ├── __main__.py │ ├── bundle_ops.py │ ├── cmdline_utils.py │ ├── opti_grab_bundle.py │ ├── pyvcli_cogs │ │ ├── __init__.py │ │ └── autogen_localctx.py │ ├── pyvcli_defs.py │ ├── server_ops.py │ ├── spare_parts │ │ ├── __init__.py │ │ ├── launch_game.py │ │ ├── launch_game0.py │ │ ├── launch_game1.py │ │ └── network.py │ ├── subcommand.py │ └── tileset_creator.py └── pyved_engine │ ├── Singleton.py │ ├── __init__.py │ ├── _classes.py │ ├── _ecs.py │ ├── _ecs_pattern.py │ ├── _hub.py │ ├── add_ons │ ├── __init__.py │ ├── gui │ │ ├── BaseGuiElement.py │ │ ├── Button.py │ │ ├── Button2.py │ │ ├── DispCenteredPopup.py │ │ ├── DispPopup.py │ │ ├── Label.py │ │ ├── TextBlock.py │ │ ├── Trigger.py │ │ ├── WidgetBo.py │ │ ├── WidgetContainer.py │ │ ├── __init__.py │ │ ├── base.py │ │ └── text.py │ └── tmx │ │ ├── LICENSE │ │ ├── __init__.py │ │ ├── data.py │ │ ├── misc.py │ │ ├── pytiled_parser │ │ ├── __init__.py │ │ ├── common_types.py │ │ ├── exception.py │ │ ├── layer.py │ │ ├── parser.py │ │ ├── parsers │ │ │ ├── __init__.py │ │ │ ├── json │ │ │ │ ├── __init__.py │ │ │ │ ├── layer.py │ │ │ │ ├── properties.py │ │ │ │ ├── tiled_map.py │ │ │ │ ├── tiled_object.py │ │ │ │ ├── tileset.py │ │ │ │ └── wang_set.py │ │ │ └── tmx │ │ │ │ ├── __init__.py │ │ │ │ ├── layer.py │ │ │ │ ├── properties.py │ │ │ │ ├── tiled_map.py │ │ │ │ ├── tiled_object.py │ │ │ │ ├── tileset.py │ │ │ │ └── wang_set.py │ │ ├── properties.py │ │ ├── tiled_map.py │ │ ├── tiled_object.py │ │ ├── tileset.py │ │ ├── util.py │ │ ├── version.py │ │ ├── wang_set.py │ │ └── world.py │ │ └── ztilemap.py │ ├── caps │ ├── __init__.py │ ├── bioslike │ │ ├── KataFrameC.py │ │ ├── KataFrameM.py │ │ ├── KataFrameV.py │ │ ├── MicroView.py │ │ └── __init__.py │ ├── engine_ground │ │ ├── StContainer.py │ │ ├── __init__.py │ │ └── util.py │ ├── networking │ │ ├── AsyncMessagingCtrl.py │ │ ├── EnvoiAsynchrone2.py │ │ ├── __init__.py │ │ └── httpserver.py │ └── struct │ │ ├── __init__.py │ │ └── matricks.py │ ├── compo │ ├── GameTpl.py │ ├── SpriteSheet.py │ ├── __init__.py │ ├── gfx.py │ ├── modes.py │ ├── packed_capello_ft.py │ └── vscreen.py │ ├── context_bridge.py │ ├── core │ ├── Injector.py │ ├── __init__.py │ ├── events.py │ └── legacy_evs.py │ ├── custom_struct.py │ ├── evsys0.py │ ├── foundation │ ├── __init__.py │ ├── defs.py │ ├── interfaces.py │ └── pbackends.py │ ├── gamedev_api │ ├── __init__.py │ ├── highlevel.py │ └── local_context.py │ ├── looparts │ ├── __init__.py │ ├── ai │ │ ├── FSA_classes_base.py │ │ ├── NorrecBrain.py │ │ ├── __init__.py │ │ └── tests.py │ ├── anim.py │ ├── ascii.py │ ├── console.py │ ├── demolib │ │ ├── __init__.py │ │ ├── animobs.py │ │ ├── dialogue.py │ │ ├── pathfinding.py │ │ └── rpgmenu.py │ ├── isometric │ │ ├── IsometricMapViewer.py │ │ ├── IsometricMapViewer0.py │ │ ├── __init__.py │ │ ├── extras.py │ │ ├── flags.py │ │ ├── isosm_config.py │ │ └── model.py │ ├── polarbear │ │ ├── __init__.py │ │ ├── frects.py │ │ ├── general.py │ │ ├── image.py │ │ └── widgets.py │ ├── rogue.py │ ├── rpg.py │ ├── story.py │ ├── sysconsole.py │ ├── tabletop.py │ └── terrain.py │ ├── pal.py │ ├── state_management.py │ ├── tankui.py │ ├── util.py │ └── vars.py └── tests ├── cards_testing.py ├── cartes.json ├── cartes.png ├── cb_test.py ├── evsys4_test.py ├── evsys6_test.py ├── rpg_testing.py ├── struct_tree.py └── test_engine.py /.github/workflows/dry-run-publish.yml: -------------------------------------------------------------------------------- 1 | # .github/workflows/publish-to-testpypi.yml 2 | name: Publish Python distrib to TestPyPI 3 | 4 | on: 5 | workflow_dispatch: 6 | 7 | permissions: 8 | contents: read 9 | 10 | jobs: 11 | build-and-test: 12 | name: Build and publish Python 🐍 distributions 📦 to TestPyPI 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v3 17 | - name: Set up Python 18 | uses: actions/setup-python@v4 19 | with: 20 | python-version: '3.x' 21 | 22 | - name: Install pypa/build 23 | run: python -m pip install build --user 24 | 25 | - name: Build a binary wheel and a source tarball 26 | run: python -m build --sdist --wheel --outdir dist/ 27 | 28 | - name: Publish distribution 📦 to Test PyPI 29 | uses: pypa/gh-action-pypi-publish@release/v1 30 | with: 31 | password: ${{ secrets.TEST_PYPI_API_TOKEN }} 32 | repository-url: https://test.pypi.org/legacy/ 33 | -------------------------------------------------------------------------------- /.github/workflows/mk.yml: -------------------------------------------------------------------------------- 1 | name: sync-docs 2 | 3 | # Controls when the workflow will run 4 | on: 5 | # Triggers the workflow on push or pull request events but only for the master branch 6 | push: 7 | branches: [ master ] 8 | paths: 9 | - 'docs/**' 10 | # Allows you to run this workflow manually from the Actions tab 11 | workflow_dispatch: 12 | 13 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 14 | jobs: 15 | # This workflow contains a single job called "build" 16 | build: 17 | # The type of runner that the job will run on 18 | runs-on: ubuntu-latest 19 | # Steps represent a sequence of tasks that will be executed as part of the job 20 | steps: 21 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 22 | - uses: actions/checkout@v2 23 | with: 24 | fetch-depth: 0 25 | - uses: actions/setup-python@v2 26 | - run: pip install mkdocs mkdocs-material==9.1.14 mkdocs-static-i18n==0.56 27 | - run: git config user.name 'github-actions[bot]' && git config user.email 'github-actions[bot]@users.noreply.github.com' 28 | - name: Publish docs 29 | run: mkdocs gh-deploy 30 | -------------------------------------------------------------------------------- /.github/workflows/python-publish.yml: -------------------------------------------------------------------------------- 1 | # .github/workflows/publish-to-pypi.yml 2 | name: Publish Python distrib to PyPI 3 | 4 | on: 5 | push: 6 | tags: 7 | - '*' 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | build-n-publish: 14 | name: Build and publish Python 🐍 distributions 📦 to PyPI 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v3 19 | - name: Set up Python 20 | uses: actions/setup-python@v4 21 | with: 22 | python-version: '3.x' 23 | 24 | - name: Install pypa/build 25 | run: >- 26 | python -m 27 | pip install 28 | build 29 | --user 30 | - name: Build a binary wheel and a source tarball 31 | run: >- 32 | python -m 33 | build 34 | --sdist 35 | --wheel 36 | --outdir dist/ 37 | . 38 | 39 | - name: Publish distribution 📦 to PyPI 40 | uses: pypa/gh-action-pypi-publish@release/v1 41 | with: 42 | password: ${{ secrets.PYPI_API_TOKEN }} 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # add-on 2 | .idea/ 3 | site/ 4 | 5 | # Byte-compiled / optimized / DLL files 6 | __pycache__/ 7 | *.py[cod] 8 | *$py.class 9 | 10 | # C extensions 11 | *.so 12 | 13 | # Distribution / packaging 14 | .Python 15 | build/ 16 | develop-eggs/ 17 | dist/ 18 | downloads/ 19 | eggs/ 20 | .eggs/ 21 | lib/ 22 | lib64/ 23 | parts/ 24 | sdist/ 25 | var/ 26 | wheels/ 27 | pip-wheel-metadata/ 28 | share/python-wheels/ 29 | *.egg-info/ 30 | .installed.cfg 31 | *.egg 32 | MANIFEST 33 | 34 | # PyInstaller 35 | # Usually these files are written by a python script from a template 36 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 37 | *.manifest 38 | *.spec 39 | 40 | # Installer logs 41 | pip-log.txt 42 | pip-delete-this-directory.txt 43 | 44 | # Unit test / coverage reports 45 | htmlcov/ 46 | .tox/ 47 | .nox/ 48 | .coverage 49 | .coverage.* 50 | .cache 51 | nosetests.xml 52 | coverage.xml 53 | *.cover 54 | *.py,cover 55 | .hypothesis/ 56 | .pytest_cache/ 57 | 58 | # Translations 59 | *.mo 60 | *.pot 61 | 62 | # Django stuff: 63 | *.log 64 | local_settings.py 65 | db.sqlite3 66 | db.sqlite3-journal 67 | 68 | # Flask stuff: 69 | instance/ 70 | .webassets-cache 71 | 72 | # Scrapy stuff: 73 | .scrapy 74 | 75 | # Sphinx documentation 76 | docs/_build/ 77 | 78 | # PyBuilder 79 | target/ 80 | 81 | # Jupyter Notebook 82 | .ipynb_checkpoints 83 | 84 | # IPython 85 | profile_default/ 86 | ipython_config.py 87 | 88 | # pyenv 89 | .python-version 90 | 91 | # pipenv 92 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 93 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 94 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 95 | # install all needed dependencies. 96 | #Pipfile.lock 97 | 98 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 99 | __pypackages__/ 100 | 101 | # Celery stuff 102 | celerybeat-schedule 103 | celerybeat.pid 104 | 105 | # SageMath parsed files 106 | *.sage.py 107 | 108 | # Environments 109 | .env 110 | .venv 111 | env/ 112 | venv/ 113 | ENV/ 114 | env.bak/ 115 | venv.bak/ 116 | 117 | # Spyder project settings 118 | .spyderproject 119 | .spyproject 120 | 121 | # Rope project settings 122 | .ropeproject 123 | 124 | # mkdocs documentation 125 | /site 126 | 127 | # mypy 128 | .mypy_cache/ 129 | .dmypy.json 130 | dmypy.json 131 | 132 | # Pyre type checker 133 | .pyre/ 134 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include src/pyvcmdline/template_0/cartridge/*.png 2 | include src/pyvcmdline/template_1/cartridge/*.png 3 | include src/pyvcmdline/template_2/cartridge/*.ncsv 4 | include src/pyvcmdline/template_2/cartridge/*.png 5 | include src/pyvcmdline/template_3/cartridge/*.png 6 | include src/pyvcmdline/template_3/cartridge/*.txt 7 | include src/pyvcmdline/template_4/cartridge/*.png 8 | include src/pyvcmdline/template_4/cartridge/*.txt 9 | include src/pyvcmdline/template_4/cartridge/*.json -------------------------------------------------------------------------------- /Pipfile: -------------------------------------------------------------------------------- 1 | [requires] 2 | python_version = "3.8.10" 3 | 4 | [packages] 5 | pygame = "==2.1.1" 6 | -------------------------------------------------------------------------------- /create_man/build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | cd .. 3 | mkdocs build 4 | copy create_man\test-website.py .\site 5 | cd create_man -------------------------------------------------------------------------------- /create_man/requirements.txt: -------------------------------------------------------------------------------- 1 | mkdocs>=1.2.1 2 | mkdocs-material==7.1.0 3 | mkdocs-static-i18n >= 0.18 4 | -------------------------------------------------------------------------------- /create_man/test-website.py: -------------------------------------------------------------------------------- 1 | import http.server 2 | # from http.server import HTTPServer, BaseHTTPRequestHandler 3 | import socketserver 4 | # import sys 5 | 6 | 7 | PORT = 8000 8 | 9 | 10 | def do_serve(): 11 | Handler = http.server.SimpleHTTPRequestHandler 12 | 13 | Handler.extensions_map={ 14 | '.manifest': 'text/cache-manifest', 15 | '.html': 'text/html', 16 | '.txt': 'text/plain', 17 | '.png': 'image/png', 18 | '.jpg': 'image/jpg', 19 | '.svg': 'image/svg+xml', 20 | '.css': 'text/css', 21 | '.js': 'application/x-javascript', 22 | '.json': 'application/json', 23 | '.xml': 'application/xml', 24 | '.wasm': 'application/wasm', 25 | '': 'application/octet-stream', # Default 26 | } 27 | 28 | httpd = socketserver.TCPServer(("", PORT), Handler) 29 | 30 | print("serving at port", PORT) 31 | print("serving at http://127.0.0.1:{}/".format(PORT)) 32 | httpd.serve_forever() 33 | 34 | 35 | if __name__ == '__main__': 36 | do_serve() 37 | -------------------------------------------------------------------------------- /docs/GameTutorials/img/breakoutend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/docs/GameTutorials/img/breakoutend.png -------------------------------------------------------------------------------- /docs/GameTutorials/img/breakoutmid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/docs/GameTutorials/img/breakoutmid.png -------------------------------------------------------------------------------- /docs/GameTutorials/img/platformerSource/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/docs/GameTutorials/img/platformerSource/background.png -------------------------------------------------------------------------------- /docs/GameTutorials/img/platformerSource/barry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/docs/GameTutorials/img/platformerSource/barry.png -------------------------------------------------------------------------------- /docs/GameTutorials/img/platformerSource/wall_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/docs/GameTutorials/img/platformerSource/wall_small.png -------------------------------------------------------------------------------- /docs/GameTutorials/img/rogueSource/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/docs/GameTutorials/img/rogueSource/image.png -------------------------------------------------------------------------------- /docs/GameTutorials/img/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/docs/GameTutorials/img/screenshot.png -------------------------------------------------------------------------------- /docs/Other patterns/Event based programming.md: -------------------------------------------------------------------------------- 1 | 2 | In the realm of game development, the Mediator Pattern serves as a crucial architectural 3 | concept. Think of it as the bridge that connects various game elements and entities, 4 | allowing for seamless interaction. Much like assembling game components into a cohesive 5 | whole, the Mediator Pattern simplifies the orchestration of complex systems, ensuring 6 | smoother gameplay and reduced confusion. 7 | 8 | ![Mediator](../images/mediator.webp "Mediator diagram") 9 | 10 | credit : 11 | -------------------------------------------------------------------------------- /docs/Other patterns/MVC examples.md: -------------------------------------------------------------------------------- 1 | 2 | MVC, or Model-View-Controller, is a foundational architectural pattern 3 | that has long been a cornerstone in software development. It divides an application 4 | into three interconnected components: Model, View, and Controller. Much like separate 5 | pieces of a well-organized puzzle, these components work in harmony 6 | to create a structured and efficient software system. 7 | 8 | 9 | ![MVC](../images/mvc1.ppm "MVC diagram") 10 | 11 | Image credit: 12 | 13 | 14 | ![MVC](../images/mvc.jpg "MVC diagram") 15 | 16 | Image credit: 17 | 18 | -------------------------------------------------------------------------------- /docs/Reference/Gamestates.md: -------------------------------------------------------------------------------- 1 | 2 | ### About gamestates 3 | 4 | When your game starts to be complex, this will require you to use what 5 | is known as 'Gamestates'. 6 | 7 | A game state is a mode in the game that is relatively independant from other modes. 8 | It uses a view and a set of actions that the user can perform. 9 | 10 | For example, it many games you will find a **Title screen**, where controls 11 | are different from controls you will find in the game itself (if it is an action game, in the game itself you will 12 | shoot enemies, whereas in the *Title screen* you only select options) 13 | 14 | ### Declare your game states 15 | 16 | You will need a file where you declare all your gamestates, like this: 17 | 18 | ``` py 19 | # import ok for development mode 20 | import pyved_engine as pyv 21 | 22 | # in production mode, its recommended to use: 23 | # from . import pimodules 24 | # pyv = pimodules.pyved_engine 25 | 26 | pyv.declare_game_states(GameStates, { 27 | GameStates.TitleScreen: MyStateA, 28 | Gamestates.Shooter: MystateB 29 | }) 30 | ``` 31 | 32 | ... But before that, the variable `GameStates` needs to be defined such as: 33 | ``` py 34 | GameStates = pyv.e_struct.enum( 35 | 'TitleScreen', 'Shooter' 36 | ) 37 | ``` 38 | Values found in the dictionary passed to `declare_game_states` are classes 39 | that inherit from the engine's core class `BaseGameState`, for example: 40 | 41 | ``` py 42 | class PuzzleState(pyv.BaseGameState): 43 | def __init__(self): 44 | # your custom code goes there 45 | pass 46 | 47 | def enter(self): 48 | # your custom code goes there 49 | pass 50 | 51 | def release(self): 52 | # your custom code goes there 53 | pass 54 | ``` 55 | -------------------------------------------------------------------------------- /docs/Reference/Using sprites.md: -------------------------------------------------------------------------------- 1 | 2 | Using sprites is an important part of any game creation task! 3 | 4 | To make this process more easy, **PYV** provides a standard format that you can use 5 | out-of-the-box and is compatible with web technologies. 6 | 7 | A *spritesheet* is basically a huge image that stores all your sprites. 8 | By using both a `.png` and a `.json` file that acts like a global index with a set 9 | of coordinates, the game engine empowers you by quickly loading all your sprites, and these 10 | sprites become available within your source-code context. 11 | 12 | To describe this quickly, and make things less abstract here's 13 | a minimalistic example of how you can handle your *spritheets*: 14 | 15 | - [Json map](https://github.com/gaudiatech/pyved-engine/blob/master/src/cartes.json) 16 | - [Image file](https://github.com/gaudiatech/pyved-engine/blob/master/src/cartes.png) 17 | 18 | The source-code that uses these files can be viewed 19 | [Here, at the given line](https://github.com/gaudiatech/pyved-engine/blob/master/src/cards_testing.py#L55). 20 | As you can see, the parameter provided is simply the name of the *spritesheet*, 21 | with no file extension. You can, however specify a path. 22 | 23 | To create *spritesheets* that stick to this format you need some tools. 24 | 25 | Here is the tool that allows you to pack or unpack *spritesheets* 26 | [TexturePacker Online](https://www.codeandweb.com/tp-online) 27 | -------------------------------------------------------------------------------- /docs/ShareYourGames.md: -------------------------------------------------------------------------------- 1 | # Share your games 2 | 3 | Our team is currently working on **an experimental feature**, 4 | once finished it will will empower you or any game developer 5 | to easily share and distribute your indie game based on "PYV"... With one single command! 6 | 7 | In the near future, typing a special command will boost your creativity! 8 | 9 | 10 | ## The experimental command 11 | 12 | Typing the command: 13 | ``` 14 | pyv-cli share myGame 15 | ``` 16 | 17 | ...Will automatically convert your python game to a HTML5-based game, 18 | upload your game to a server (*cloud storage*) automatically, and finally provide you with 19 | a link that you can share with friends. 20 | 21 | *Get feedback in matters of minutes! Not days, or weeks!* 22 | 23 | The converted result may look like this: 24 | 25 | 26 | Or this: 27 | (made during one of our previous Pyved workshops!) 28 | 29 | !!! warning 30 | if you wish to test that experimental feature, you will need the latest STABLE 31 | version of `pyved-engine` that is: the `v24.9a1`, this revision can be downloaded 32 | via PyPI 33 | 34 | 35 | ## The inspector tool 36 | 37 | Also you may be interested in checking this link: 38 | 39 | 40 | The goal is to share knowledge about game development and allow developers to easily **remix existing games**, 41 | in order to improve the content shared by the community as a whole. 42 | -------------------------------------------------------------------------------- /docs/Showcase.md: -------------------------------------------------------------------------------- 1 | # Showcase 2 | 3 | Here is a small showcase of the games created by the development to demonstrate the possibilities of pyved-engine. 4 | 5 | Note that these are only small game in order to demonstrate what's possible with our tool, you can probably make even crazier results ! 6 | 7 | ![Game examples](./images/gallery1.png "Games") 8 | ![Game examples](./images/gallery2.png "Games") 9 | 10 | 11 | ![The breakout end result](<./GameTutorials/img/breakoutend.png> "breakout") 12 | ![The patformer end result](<./GameTutorials/img/screenshot.png> "Our platformer") 13 | -------------------------------------------------------------------------------- /docs/flappybird-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/docs/flappybird-preview.png -------------------------------------------------------------------------------- /docs/image.en.fake: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/docs/image.en.fake -------------------------------------------------------------------------------- /docs/image.en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/docs/image.en.png -------------------------------------------------------------------------------- /docs/image.fr.fake: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/docs/image.fr.fake -------------------------------------------------------------------------------- /docs/image.fr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/docs/image.fr.png -------------------------------------------------------------------------------- /docs/images/ECSBlockDiagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/docs/images/ECSBlockDiagram.png -------------------------------------------------------------------------------- /docs/images/gallery1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/docs/images/gallery1.png -------------------------------------------------------------------------------- /docs/images/gallery2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/docs/images/gallery2.png -------------------------------------------------------------------------------- /docs/images/mediator.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/docs/images/mediator.webp -------------------------------------------------------------------------------- /docs/images/mvc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/docs/images/mvc.jpg -------------------------------------------------------------------------------- /docs/images/mvc1.ppm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/docs/images/mvc1.ppm -------------------------------------------------------------------------------- /docs/kengi-palette-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/docs/kengi-palette-preview.png -------------------------------------------------------------------------------- /docs/match3-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/docs/match3-preview.png -------------------------------------------------------------------------------- /examples/astero/(astero)enter_start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/astero/(astero)enter_start.png -------------------------------------------------------------------------------- /examples/astero/(astero)explosion_002.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/astero/(astero)explosion_002.wav -------------------------------------------------------------------------------- /examples/astero/(astero)ndimensions-zik.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/astero/(astero)ndimensions-zik.ogg -------------------------------------------------------------------------------- /examples/astero/(astero)rock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/astero/(astero)rock.png -------------------------------------------------------------------------------- /examples/blokumanBundle/cartridge/TetColors.py: -------------------------------------------------------------------------------- 1 | 2 | from . import glvars 3 | 4 | kengi = glvars.katasdk.pyved_engine 5 | 6 | 7 | TetColors = kengi.e_struct.enum( 8 | 'Clear', 9 | 'Gray', 10 | 'Pink' 11 | ) 12 | -------------------------------------------------------------------------------- /examples/blokumanBundle/cartridge/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/blokumanBundle/cartridge/__init__.py -------------------------------------------------------------------------------- /examples/blokumanBundle/cartridge/blokuman-bt_rouge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/blokumanBundle/cartridge/blokuman-bt_rouge.png -------------------------------------------------------------------------------- /examples/blokumanBundle/cartridge/coinhigh.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/blokumanBundle/cartridge/coinhigh.wav -------------------------------------------------------------------------------- /examples/blokumanBundle/cartridge/coinlow.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/blokumanBundle/cartridge/coinlow.wav -------------------------------------------------------------------------------- /examples/blokumanBundle/cartridge/crumble.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/blokumanBundle/cartridge/crumble.wav -------------------------------------------------------------------------------- /examples/blokumanBundle/cartridge/defs.py: -------------------------------------------------------------------------------- 1 | from . import glvars 2 | 3 | pyv = glvars.katasdk.pyved_engine 4 | 5 | GameStates = pyv.e_struct.enum( 6 | 'TitleScreen', # first in the list => initial gamestate 7 | 'Credits', 8 | 'Puzzle', 9 | 'TaxPayment' 10 | ) 11 | -------------------------------------------------------------------------------- /examples/blokumanBundle/cartridge/ev_types.py: -------------------------------------------------------------------------------- 1 | 2 | from . import glvars 3 | 4 | pyv = glvars.katasdk.pyved_engine 5 | 6 | BlokuEvents = pyv.game_events_enum(( 7 | 'Validation', 8 | 9 | # - LoginState 10 | 'LoginStUsernameChanges', # contains txt 11 | 'LoginStPwdChanges', # contains txt(not a plain pwd str!) 12 | 'LoginStFocusChanges', # contains focusing_username=True/False 13 | 'TrigValidCredentials', # no attr 14 | 'PlayerLogsIn', # sent after succesful auth, contains username:str, solde:int 15 | 16 | # - Puzzle state 17 | 'NewPieces', # bag has been re-filled, no attr 18 | 'ScoreChanges', # contient score=int 19 | 'GameLost', 20 | 'LineDestroyed', 21 | 'BlocksCrumble', 22 | 23 | # - TitleScreen state 24 | 'ChoiceChanges', # contient code 25 | 'BalanceChanges', # contiendra value (un int) 26 | 'DemandeTournoi', 27 | 28 | # - Taxpayment state 29 | 'LoadingBarMoves', 30 | )) 31 | -------------------------------------------------------------------------------- /examples/blokumanBundle/cartridge/fonts_n_colors.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | my_fonts = { 4 | # 'larger': ('freesansbold.ttf', 27), 5 | # 'xl': ('freesansbold.ttf', 35), 6 | # 'display_font': ('freesansbold.ttf', 22), 7 | # 'basic': ('freesansbold.ttf', 16), 8 | # 'medium': ('freesansbold.ttf', 21), 9 | 10 | # /!\ on avait cette font partout: 'monogram.ttf' 11 | # -multiples de 16 fortement recommandé 12 | 'tiny_monopx': (None, 16), 13 | 'sm_monopx': (None, 28), 14 | 'moderne': (None, 32), 15 | 'moderne_big': (None, 64) 16 | } 17 | 18 | my_colors = { 19 | 'bgspe_color': '#d1dbff', 20 | 21 | 'c_black': '#000000', 22 | 'c_white': '#ffffff', 23 | 'c_cherokee': '#924a40', 24 | 'c_oceanblue': '#84c5cc', 25 | 26 | 'c_plum': '#9351b6', 27 | 'c_leafgreen': '#72b14b', 28 | 'c_purple': '#483aaa', 29 | 'c_sunny': '#d5df7c', 30 | 31 | 'c_brown': '#99692d', 32 | 'c_mud': '#675200', 33 | 'c_skin': '#c18178', 34 | 'c_gray1': '#606060', 35 | 36 | 'c_gray2': '#8a8a8a', 37 | 'c_pastelgreen': '#b3ec91', 38 | 'c_lightpurple': '#867ade', 39 | 'c_gray3': '#b3b3b3', 40 | } 41 | -------------------------------------------------------------------------------- /examples/blokumanBundle/cartridge/gamedef.py: -------------------------------------------------------------------------------- 1 | # import sharedvars 2 | from . import pimodules 3 | from . import glvars as vars 4 | 5 | vars.katasdk = pimodules 6 | pyv = pimodules.pyved_engine 7 | 8 | pyv.bootstrap_e() 9 | 10 | pyg = pyv.pygame 11 | # sharedvars.katasdk 12 | from . import util 13 | 14 | util.init_fonts_n_colors() # need to init colors before loading TitleView, otherwise --> crash! 15 | 16 | # from katagames_sdk.capsule.networking.httpserver import HttpServer 17 | from .defs import GameStates 18 | from . import loctexts 19 | from .puzzle_state import PuzzleState 20 | from .menu_state import TitleScreenState 21 | from .ev_types import BlokuEvents 22 | from . import glvars 23 | 24 | # TODO: fix 25 | HttpServer = None 26 | 27 | 28 | # HttpServer = old_v_kengi.network.HttpServer # katasdk.network.HttpServer in future versions 29 | 30 | 31 | # class BlokuGame(kengi.GameTpl): 32 | # 33 | # 34 | # # xxx DOUBLEMENT deprecated xxx 35 | # ## - juste un test réseau, ce reset game ne sert a rien pour BLOKU-MAN, 36 | # ## il est utile pour mConquest... 37 | # ## serv = HttpServer.instance() 38 | # ## url = 'https://sc.gaudia-tech.com/tom/' 39 | # ## params = {} 40 | # ## full_script = url+'resetgame.php' 41 | # ## print(full_script) 42 | # ## res = serv.proxied_get(full_script, params) 43 | # ## game_ctrl = kengi.get_game_ctrl() 44 | # ## game_ctrl.turn_on() 45 | # 46 | # important! Its needed to proc the 1st gstate 'do_init' method 47 | # self._manager.post(kengi.EngineEvTypes.Gamestart) 48 | 49 | 50 | # blokuwrapper.glvars.gameref = game = BlokuGame() 51 | # katasdk.gkart_activation(game) 52 | 53 | 54 | # TODO rewrite the game loop/boilerplate 55 | class BlokumanGame(pyv.GameTpl): 56 | 57 | def get_video_mode(self): 58 | return 1 59 | 60 | def list_game_events(self): 61 | return BlokuEvents 62 | 63 | def enter(self, vms=None): 64 | # safer this way: 65 | self.nxt_game = 'game_selector' 66 | loctexts.init_repo(glvars.CHOSEN_LANG) 67 | super().enter(vms) 68 | pyv.declare_game_states( # doit etre appelé après le setup_ev_manager !!! 69 | GameStates, 70 | { 71 | GameStates.TitleScreen: TitleScreenState, 72 | GameStates.Puzzle: PuzzleState 73 | } 74 | ) 75 | 76 | 77 | game = BlokumanGame() 78 | -------------------------------------------------------------------------------- /examples/blokumanBundle/cartridge/glvars.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | # GLOBAL VARS 6 | # ---------------------- 7 | katasdk = None 8 | util = None 9 | 10 | username = None 11 | acc_id = None 12 | 13 | # specific 14 | solde_gp = None 15 | border_fade_colour = None 16 | colour_map = None 17 | song = None 18 | snd_channels = dict() 19 | num_lastchannel = 0 # pr alterner entre 0 et 1 20 | copie_solde = None 21 | colors = dict() 22 | fonts = dict() 23 | num_challenge = None # sera un entier 24 | chall_seed = 1 # sera un entier déterminant cmt générateur aléatoire va sortir les données du problème d'optim. 25 | multiplayer_mode = None # sera déterminé en fct de s'il y a des joueurs "remote" 26 | server_host = None # recevra un str 27 | server_port = None # recevra un int 28 | server_debug = None 29 | 30 | # ---------------------- 31 | # CONSTANTS 32 | # ---------------------- 33 | DEV_MODE = True 34 | GAME_ID = 8 # 8 pour blokuman, c codé en dur coté serv 35 | SKIP_MINING = False 36 | SQ_SIZE = 20 37 | BORDER_SIZE = 3 38 | MAX_FPS = 45 39 | VERSION = '0.20.1a' 40 | RESSOURCE_LOC = ['assets'] 41 | CHOSEN_LANG = 'fr' 42 | # codes 43 | NOP, CHOIX_LOGIN, CHOIX_START, CHOIX_CRED, CHOIX_QUIT = range(5) -------------------------------------------------------------------------------- /examples/blokumanBundle/cartridge/labels.py: -------------------------------------------------------------------------------- 1 | from . import glvars 2 | 3 | 4 | kengi = glvars.katasdk.pyved_engine 5 | 6 | 7 | Labels = kengi.e_struct.enum( 8 | 'PoidsTotal', 9 | 'UtiliteTotale', 10 | 11 | 'Minage1', # titre affiché pr le mode taxe 12 | 'Minage2', # phrase attente 13 | 14 | 'WindowCaption', 15 | 'Utilisateur', 16 | 'Solde', 17 | 'Invite', 18 | 19 | 'NomJoueurAnonyme', 20 | 21 | 'EndEasyWin', 22 | 'EndEasyLoose', 23 | 24 | 'EndChallenge1', 25 | 26 | 'EndGameAction', # pr indiquer ce que lutilisateur doit faire 27 | 28 | 'SensLogin', # titre mode login 29 | 30 | 'WordLogin', 31 | 'WordPassword', 32 | 33 | 'OpenBrowser', 34 | 'CanCreateAcc', # phrase pr dire tu peux taper les infos! 35 | 'InciteLudoStore', 36 | 37 | 'CannotLogin', 38 | 'Connexion', 39 | 40 | 'MenuDefi', 41 | 42 | 'MenuGridGame', # nom bouton pour exec. grid game 43 | 44 | 'MenuTuto', 45 | 'MenuEntrainement', 46 | 'MenuQuitter', 47 | 48 | 'RetourArr', 49 | 50 | 'NoTraining', 51 | 52 | 'CompteRequis', 53 | 'CoutDefi' 54 | ) 55 | -------------------------------------------------------------------------------- /examples/blokumanBundle/cartridge/metadat.json: -------------------------------------------------------------------------------- 1 | { 2 | "vmlib_ver": "23_8a5", 3 | "dependencies": { 4 | "pyved_engine": "23.4a4" 5 | }, 6 | "description": "Its a puzzle game and its pretty basic!", 7 | "author": "Thomas", 8 | "assets": [ 9 | "blokuman-bt_rouge.png" 10 | ], 11 | "sounds": [ 12 | "crumble.wav", 13 | "coinhigh.wav", 14 | "coinlow.wav" 15 | ], 16 | "game_name": "blokuman", 17 | "cartridge": "blokumanBundle", 18 | "build_date": "Tue Aug 22 20:46:22 2023" 19 | } -------------------------------------------------------------------------------- /examples/blokumanBundle/cartridge/pimodules.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | upward_link = None 4 | 5 | 6 | def __getattr__(name): 7 | global upward_link 8 | # debug 9 | # print('pimodules is tryin to provide...', name) 10 | return upward_link[name] 11 | -------------------------------------------------------------------------------- /examples/blokumanBundle/cartridge/util.py: -------------------------------------------------------------------------------- 1 | 2 | from . import glvars 3 | from .TetColors import TetColors 4 | 5 | # ---------------------- 6 | # UTIL. FUNCTIONS 7 | # ---------------------- 8 | # def cli_logout(): 9 | # global nom_utilisateur, solde_gp, id_perso 10 | # nom_utilisateur = solde_gp = id_perso = None 11 | 12 | 13 | def load_server_config(): 14 | import os 15 | f = open(os.path.join('server.cfg')) 16 | 17 | config_externe = f.readlines() 18 | global server_host, server_port, server_debug 19 | k = int(config_externe[0]) 20 | server_debug = False if (k == 0) else True 21 | server_host = config_externe[1].strip("\n") 22 | server_port = int(config_externe[2]) 23 | 24 | 25 | def init_sound(): 26 | pyg = glvars.katasdk.pyved_engine.pygame 27 | if len(glvars.snd_channels) < 1: 28 | capital_n = 3 29 | pyg.mixer.set_num_channels(capital_n) 30 | for k in range(capital_n): 31 | glvars.snd_channels[k] = pyg.mixer.Channel(k) 32 | 33 | 34 | def is_sfx_playin(): 35 | for cn in range(2): 36 | if glvars.snd_channels[cn].get_busy(): 37 | return True 38 | 39 | return False 40 | 41 | 42 | def playmusic(): 43 | pass 44 | # global snd_channels, song 45 | # 46 | # if not katasdk.runs_in_web(): 47 | # 48 | # if song is None: 49 | # pygame.mixer.music.load('user_assets/chiptronic.ogg') 50 | # song = 1 51 | # pygame.mixer.music.play(-1) 52 | 53 | 54 | def playsfx(pygamesound): 55 | # ToDO temp fix for webctx 56 | # global snd_channels, num_lastchannel 57 | # if not katasdk.runs_in_web(): 58 | # num_lastchannel = (num_lastchannel + 1) % 2 59 | # snd_channels[num_lastchannel].play(pygamesound) 60 | pygamesound.play() 61 | 62 | 63 | def init_fonts_n_colors(): 64 | from .fonts_n_colors import my_fonts, my_colors 65 | import os 66 | 67 | # global border_fade_colour, colour_map, colors, fonts 68 | pyg = glvars.katasdk.pyved_engine.pygame 69 | border_fade_colour = pyg.Color(50, 50, 50) 70 | 71 | # - BLOc standardisé - 72 | pyg.font.init() 73 | for name, v in my_colors.items(): 74 | glvars.colors[name] = pyg.Color(v) 75 | ressource_loc_li = ['.'] 76 | for name, t in my_fonts.items(): 77 | if t[0] is not None: 78 | tmp = list(ressource_loc_li) 79 | tmp.append(t[0]) 80 | source = os.path.join(*tmp) 81 | else: 82 | source = None 83 | glvars.fonts[name] = pyg.font.Font(source, t[1]) 84 | print('chargement fonts_n_colors *** OK!') 85 | 86 | # pygame.font.init() 87 | # for name, v in my_colors.items(): 88 | # colors[name] = pygame.Color(v) 89 | # for name, t in my_fonts.items(): 90 | # tmp = list(RESSOURCE_LOC) 91 | # tmp.append(t[0]) 92 | # source = os.path.join(*tmp) 93 | # fonts[name] = pygame.font.Font(source, t[1]) 94 | 95 | # bonus algo, helper pour afficher tetromino sprites... 96 | glvars.colour_map = { 97 | TetColors.Gray: glvars.colors['c_gray2'], 98 | TetColors.Clear: glvars.colors['bgspe_color'], #colors['c_lightpurple'], 99 | TetColors.Pink: glvars.colors['c_skin'] 100 | } 101 | -------------------------------------------------------------------------------- /examples/blokumanBundle/vmslateL.py: -------------------------------------------------------------------------------- 1 | """ 2 | **Never edit that file!** 3 | 4 | Its part of the pyved_engine. 5 | 6 | The code below is standardized code (required to defined any GameBundleL), 7 | it helps in booting up the internal game cartridge (aka the PyvGC format) 8 | 9 | {{N.B. Tom }} 10 | In general its not recommanded to run that script directly, 11 | its way better to use `pyv-cli play GameBundleName` ... 12 | THAT BEING SAID, see the comment at the end of the file 13 | """ 14 | 15 | 16 | def bootgame(metadata): 17 | try: 18 | import vm 19 | rel_imports = False 20 | except ModuleNotFoundError: 21 | from . import vm 22 | rel_imports = True 23 | 24 | mon_inj = vm.Injector(None) 25 | mon_inj.set_lazy_loaded_module('pyved_engine', 'pyved_engine') 26 | mon_inj.set_lazy_loaded_module('math', 'math') 27 | vm.upward_link(mon_inj) 28 | 29 | if rel_imports: 30 | from .cartridge import pimodules 31 | pimodules.upward_link = mon_inj 32 | from .cartridge import gamedef 33 | vm.game_execution(metadata, gamedef) 34 | else: 35 | from cartridge import pimodules 36 | pimodules.upward_link = mon_inj 37 | from cartridge import gamedef 38 | vm.game_execution(metadata, gamedef) 39 | 40 | 41 | # I still keep the code below as its handy to allow the script direct execution in rare situations 42 | if __name__ == '__main__': 43 | import json 44 | with open('cartridge/metadat.json', 'r') as fp: 45 | bootgame(json.load(fp)) 46 | -------------------------------------------------------------------------------- /examples/bubbleshooter/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/bubbleshooter/__init__.py -------------------------------------------------------------------------------- /examples/capello-ft/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Aseprite Font 2 | Copyright (C) 2001-2017 David Capello 3 | http://www.aseprite.org/ 4 | 5 | This work is licensed under the Creative Commons Attribution 4.0 6 | International License. To view a copy of this license, visit 7 | http://creativecommons.org/licenses/by/4.0/ or send a letter to 8 | Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. 9 | -------------------------------------------------------------------------------- /examples/capello-ft/capello-ft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/capello-ft/capello-ft.png -------------------------------------------------------------------------------- /examples/capello-ft/datapacker.py: -------------------------------------------------------------------------------- 1 | import base64 2 | 3 | #I used base64.b64encode(fptr)... 4 | # Use base64.b64decode(encoded) to decode! 5 | 6 | f = open('capello-ft.json', 'r') 7 | #base64.b64encode(f.read()) 8 | s = f.read() 9 | 10 | 11 | import re 12 | s = re.sub('[\s+]', '', s) 13 | with open('packedjson.py', 'w') as f2: 14 | print('content='+s,file=f2) 15 | 16 | f.close() 17 | print('done.') 18 | -------------------------------------------------------------------------------- /examples/conversation/main.py: -------------------------------------------------------------------------------- 1 | import katagames_engine as kengi 2 | 3 | kengi.bootstrap_e() 4 | 5 | kengi.ai.tests.run_test() 6 | -------------------------------------------------------------------------------- /examples/cutscene_exp/core_component.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class Component: 4 | """ 5 | Base class for all components 6 | """ 7 | def __init__(self): 8 | self.key = None 9 | self.init() 10 | 11 | def init(self): 12 | pass 13 | 14 | def reset(self): 15 | pass 16 | -------------------------------------------------------------------------------- /examples/cutscene_exp/cutscene.py: -------------------------------------------------------------------------------- 1 | from math import ceil 2 | import gamedefs 3 | # from ..gamma import windowSize 4 | # from ..utils.utils import drawRect 5 | # from .colours import * 6 | from rectangle import Rectangle 7 | 8 | 9 | class Cutscene: 10 | 11 | def __init__(self): 12 | # list of actions to perform 13 | self.actionList = [] 14 | # current action to perform 15 | self.actionIndex = 0 16 | 17 | self.fadePercentage = 0 18 | self.inOutDuration = 60 19 | self.lettboxColour = "black" # BLACK 20 | self.lettboxHeight = 30 21 | 22 | # status is either: 23 | # in = fading in 24 | # do = performing the scene 25 | # out = fading out 26 | self.status = 'in' 27 | 28 | self.currentDelay = 0 29 | 30 | def setDelay(self, amount): 31 | self.currentDelay = amount 32 | 33 | def advance(self): 34 | self.actionIndex += 1 35 | 36 | def reset(self): 37 | self.actionIndex = 0 38 | self.fadePercentage = 0 39 | self.status = 'in' 40 | 41 | def update(self, scene): 42 | # fading in 43 | if self.status == 'in': 44 | self.fadePercentage = min(100, self.fadePercentage+(100/self.inOutDuration)) 45 | if self.fadePercentage == 100: 46 | self.status = 'do' 47 | 48 | # fading out 49 | if self.status == 'out': 50 | self.fadePercentage = max(0, self.fadePercentage-(100/self.inOutDuration)) 51 | if self.fadePercentage == 0: 52 | scene.cutScene = None 53 | 54 | # performing cutscene 55 | if self.status == 'do': 56 | 57 | if len(self.actionList) > self.actionIndex: 58 | if self.currentDelay == 0: 59 | self.actionList[self.actionIndex]() 60 | if self.currentDelay == 0: 61 | self.advance() 62 | 63 | if self.currentDelay > 0: 64 | self.currentDelay -= 1 65 | if self.currentDelay == 0: 66 | self.advance() 67 | 68 | else: 69 | self.status = 'out' 70 | 71 | def draw(self, scene): 72 | # top letterbox 73 | Rectangle( 74 | 0, 0, 75 | gamedefs.WIDTH, ceil(self.lettboxHeight * (self.fadePercentage / 100)), 76 | colour=self.lettboxColour 77 | ).draw(scene.surface) 78 | 79 | # bottom letterbox 80 | Rectangle( 81 | 0, ceil(gamedefs.HEIGHT - (self.lettboxHeight * (self.fadePercentage / 100))), 82 | gamedefs.WIDTH, self.lettboxHeight * (self.fadePercentage / 100), 83 | colour=self.lettboxColour 84 | ).draw(scene.surface) 85 | -------------------------------------------------------------------------------- /examples/cutscene_exp/gamedefs.py: -------------------------------------------------------------------------------- 1 | 2 | WIDTH = 960 3 | HEIGHT = 720 4 | SCR_SIZE = (WIDTH, HEIGHT) 5 | -------------------------------------------------------------------------------- /examples/cutscene_exp/manager_scene.py: -------------------------------------------------------------------------------- 1 | class SceneManager: 2 | 3 | def __init__(self): 4 | self.storedScenes = {} 5 | self.scenes = [] 6 | self.transition = None 7 | 8 | def storeScene(self, tag, scene): 9 | self.storedScenes[tag] = scene 10 | 11 | def getStoredScene(self, tag): 12 | return self.storedScenes[tag] 13 | 14 | def isEmpty(self): 15 | return len(self.scenes) == 0 16 | 17 | def enterScene(self): 18 | if len(self.scenes) > 0: 19 | self.getTopScene()._onEnter() 20 | 21 | def exitScene(self): 22 | if len(self.scenes) > 0: 23 | self.getTopScene()._onExit() 24 | 25 | def update(self): 26 | if self.transition is not None: 27 | self.transition._update() 28 | else: 29 | if len(self.scenes) > 0: 30 | self.getTopScene()._update() 31 | 32 | def draw(self): 33 | if self.transition is not None: 34 | self.transition._draw() 35 | else: 36 | if len(self.scenes) > 0: 37 | self.getTopScene()._draw() 38 | 39 | def push(self, scene): 40 | if not scene.drawSceneBelow: 41 | self.exitScene() 42 | self.scenes.append(scene) 43 | self.enterScene() 44 | 45 | def pop(self, scenesToPop=1): 46 | for i in range(scenesToPop): 47 | scene = self.getTopScene() 48 | self.exitScene() 49 | self.scenes.pop() 50 | if not scene.drawSceneBelow: 51 | self.enterScene() 52 | 53 | def set(self, scenes): 54 | # pop all scenes 55 | while len(self.scenes) > 0: 56 | self.pop() 57 | # add new scenes 58 | for s in scenes: 59 | self.scenes.append(s) # push(s)? 60 | # enter the top scene 61 | self.enterScene() 62 | 63 | def clear(self): 64 | while len(self.scenes) > 0: 65 | self.pop() 66 | 67 | def setTransition(self, t): 68 | self.transition = t 69 | 70 | def getTopScene(self): 71 | if len(self.scenes) == 0: 72 | return None 73 | return self.scenes[-1] 74 | 75 | def getSceneBelow(self, scene): 76 | if scene not in self.scenes: 77 | return self.getTopScene() 78 | if len(self.scenes) <= 1: 79 | return None 80 | return self.scenes[self.scenes.index(scene)-1] -------------------------------------------------------------------------------- /examples/cutscene_exp/rectangle.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | # from ..core.renderable import Renderable 3 | # from ..core.colours import WHITE 4 | # from ..utils.utils_draw import blit_alpha 5 | from renderable import Renderable 6 | 7 | 8 | class Rectangle(Renderable): 9 | 10 | def __init__(self, 11 | 12 | # required parameters 13 | x, y, w, h, 14 | 15 | # optional parameters 16 | hAlign='left', vAlign='top', 17 | colour='white', 18 | alpha=255, 19 | z=1, 20 | xParallax=False, yParallax=False 21 | 22 | ): 23 | 24 | super().__init__(x, y, z, hAlign, vAlign, colour, alpha, xParallax, yParallax) 25 | 26 | # set additional text object parameters 27 | self._w = w 28 | self._h = h 29 | self._createSurface() 30 | 31 | def _createSurface(self): 32 | 33 | self.surface = pygame.Surface((self._w, self._h), pygame.SRCALPHA) 34 | self.rect = self.surface.get_rect() 35 | pygame.draw.rect(self.surface, self.colour, (0, 0, self._w, self._h)) 36 | 37 | self._align() 38 | 39 | def draw(self, surface, xOff=0, yOff=0, scale=1): 40 | 41 | x = int(self.rect.x * scale + xOff) 42 | y = int(self.rect.y * scale + yOff) 43 | w = int(self.rect.w * scale) 44 | h = int(self.rect.h * scale) 45 | 46 | if scale != 1: 47 | scaled_surface = pygame.transform.scale(self.surface, (w, h)) 48 | else: 49 | scaled_surface = self.surface 50 | 51 | if self._alpha < 255: 52 | blit_alpha(surface, scaled_surface, (x, y), self._alpha) 53 | else: 54 | surface.blit(scaled_surface, (x,y)) 55 | 56 | # dimension properties 57 | 58 | @property 59 | def w(self): 60 | return self._w 61 | 62 | @w.setter 63 | def w(self, value): 64 | self._w = value 65 | self._createSurface() 66 | 67 | @property 68 | def h(self): 69 | return self._h 70 | 71 | @h.setter 72 | def h(self, value): 73 | self._h = value 74 | self._createSurface() 75 | 76 | -------------------------------------------------------------------------------- /examples/cutscene_exp/renderable.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class Renderable: 4 | 5 | def __init__(self, x, y, z, h, v, c, a=255, xp=False, yp=False): 6 | 7 | self._x = x 8 | self._y = y 9 | self.z = z 10 | self.hAlign = h 11 | self.vAlign = v 12 | self.colour = c 13 | self._alpha = a 14 | self.xp = xp 15 | self.yp = yp 16 | 17 | def _align(self): 18 | 19 | if self.rect is None: 20 | return 21 | 22 | # adjust x position for horizontal anchor 23 | if self.hAlign == 'left': 24 | self.rect.x = self._x 25 | if self.hAlign == 'center': 26 | self.rect.centerx = self._x 27 | if self.hAlign == 'right': 28 | self.rect.right = self._x 29 | 30 | # adjust y position for vertical anchor 31 | if self.vAlign == 'top': 32 | self.rect.y = self._y 33 | if self.vAlign == 'middle': 34 | self.rect.centery = self._y 35 | if self.vAlign == 'bottom': 36 | self.rect.bottom = self._y 37 | 38 | def _createSurface(self): 39 | pass 40 | 41 | # alpha property 42 | 43 | @property 44 | def alpha(self): 45 | return self._alpha 46 | 47 | @alpha.setter 48 | def alpha(self, value): 49 | self._alpha = value 50 | self._createSurface() 51 | 52 | # position properties 53 | 54 | @property 55 | def x(self): 56 | return self._x 57 | 58 | @x.setter 59 | def x(self, value): 60 | self._x = value 61 | self.hAlign = 'left' 62 | self._align() 63 | 64 | @property 65 | def y(self): 66 | return self._y 67 | 68 | @y.setter 69 | def y(self, value): 70 | self._y = value 71 | self.vAlign = 'top' 72 | self._align() 73 | 74 | @property 75 | def left(self): 76 | return self.rect.x 77 | 78 | @left.setter 79 | def left(self, value): 80 | self._x = value 81 | self.hAlign = 'left' 82 | self._align() 83 | 84 | @property 85 | def center(self): 86 | return self.rect.centerx 87 | 88 | @center.setter 89 | def center(self, value): 90 | self._x = value 91 | self.hAlign = 'center' 92 | self._align() 93 | 94 | @property 95 | def right(self): 96 | return self.rect.right 97 | 98 | @right.setter 99 | def right(self, value): 100 | self._x = value 101 | self.hAlign = 'right' 102 | self._align() 103 | 104 | @property 105 | def top(self): 106 | return self.rect.y 107 | 108 | @top.setter 109 | def top(self, value): 110 | self._y = value 111 | self.vAlign = 'top' 112 | self._align() 113 | 114 | @property 115 | def middle(self): 116 | return self.rect.centery 117 | 118 | @middle.setter 119 | def middle(self, value): 120 | self._y = value 121 | self.vAlign = 'middle' 122 | self._align() 123 | 124 | @property 125 | def bottom(self): 126 | return self.rect.bottom 127 | 128 | @bottom.setter 129 | def bottom(self, value): 130 | self._y = value 131 | self.vAlign = 'bottom' 132 | self._align() 133 | -------------------------------------------------------------------------------- /examples/cutscene_exp/renderer.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | 3 | 4 | class Renderer: 5 | 6 | def __init__(self, scene): 7 | 8 | # list of items to render 9 | self.worldRenderable = [] 10 | self.sceneRenderable = [] 11 | # a renderer is attached to a scene 12 | self.scene = scene 13 | 14 | # adds a renderable object to the renderer 15 | def add(self, r, scene=True): 16 | if not scene: 17 | self.worldRenderable.append(r) 18 | else: 19 | self.sceneRenderable.append(r) 20 | 21 | # removes all renderable objects from the renderer 22 | def flush(self): 23 | self.worldRenderable = [] 24 | self.sceneRenderable = [] 25 | 26 | def draw(self): 27 | 28 | # 29 | # WORLD RENDERING 30 | # draw all renderable objects, for all cameras 31 | # 32 | 33 | # iterate over all cameras 34 | entitiesWithCamera = self.scene.getEntitiesWithComponent('camera') 35 | if len(entitiesWithCamera) != 1: 36 | print(entitiesWithCamera) 37 | raise ValueError('unexpected effect') 38 | 39 | for e in entitiesWithCamera: 40 | 41 | # get the camera component 42 | camera = e['camera'] 43 | 44 | # set clipping rectangle 45 | cameraRect = camera.rect 46 | clipRect = pygame.Rect(cameraRect.x, cameraRect.y, cameraRect.w, cameraRect.h) 47 | self.scene.surface.set_clip(clipRect) 48 | 49 | # fill camera background 50 | if camera.bgColour is not None: 51 | self.scene.surface.fill(camera.bgColour) 52 | 53 | # draw each renderable, transformed for the camera 54 | for r in self.worldRenderable: 55 | r.draw(self.scene.surface, camera._x, camera._y, camera._z) 56 | 57 | # unset clipping rectangle 58 | self.scene.surface.set_clip(None) 59 | 60 | # 61 | # SCENE RENDERING 62 | # 63 | 64 | for r in self.sceneRenderable: 65 | r.draw(self.scene.surface) 66 | -------------------------------------------------------------------------------- /examples/cutscene_exp/shared.py: -------------------------------------------------------------------------------- 1 | 2 | mainScene = cutScene = None 3 | already_pressed = False 4 | -------------------------------------------------------------------------------- /examples/cutscene_exp/systems.py: -------------------------------------------------------------------------------- 1 | import pyved_engine 2 | import shared 3 | 4 | 5 | __all__ = [ # Careful: the order specified below... It really matters! 6 | 'input_system', 7 | 'update_scenes_system', 8 | 'render_graphics', 9 | ] 10 | 11 | 12 | def input_system(entities, componets): # why components? 13 | pygame = pyved_engine.pygame 14 | pkeys = pygame.key.get_pressed() 15 | if pkeys[pygame.K_RETURN]: 16 | if not shared.already_pressed: 17 | print('cutscene launched!') 18 | shared.cutScene.reset() 19 | shared.mainScene.cutscene = shared.cutScene 20 | shared.already_pressed = True 21 | else: 22 | if shared.already_pressed: 23 | shared.already_pressed = False 24 | 25 | 26 | def update_scenes_system(entities, components): 27 | shared.mainScene._update() 28 | 29 | 30 | def render_graphics(entities, components): 31 | # Clear screen before rendering 32 | pyved_engine.vars.screen.fill((0, 77, 0)) 33 | shared.mainScene._draw() 34 | # print('flip ok') 35 | pyved_engine.flip() 36 | # for entity_o in entities: 37 | # if pyv.archetype_of(entity_o) == "player": 38 | # cam = entity_o['cam'] 39 | # x, y = entity_o['position'] 40 | # pyv.draw_polygon(pyv.vars.screen, 'pink', [(x, y), (x + 20, y), (x + 10, y + 20)]) 41 | # print(dir(mainScene.renderer)) 42 | -------------------------------------------------------------------------------- /examples/cutscene_exp/vita_00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/cutscene_exp/vita_00.png -------------------------------------------------------------------------------- /examples/cutscene_exp/vita_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/cutscene_exp/vita_01.png -------------------------------------------------------------------------------- /examples/cutscene_exp/vita_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/cutscene_exp/vita_02.png -------------------------------------------------------------------------------- /examples/cutscene_exp/vita_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/cutscene_exp/vita_03.png -------------------------------------------------------------------------------- /examples/ecs_naif/demo_entities.py: -------------------------------------------------------------------------------- 1 | from typing import Iterable 2 | 3 | from pyved_engine import component, entity 4 | 5 | 6 | # ---------------------------------------- 7 | # COMPONENTS 8 | # ---------------------------------------- 9 | @component 10 | class MobPosition: 11 | x: int 12 | y: int 13 | 14 | 15 | @component 16 | class AvStyle: 17 | style: int = 0 # 0, 1, 2 are ok 18 | 19 | 20 | @component 21 | class DirMobileBehavior: 22 | angle: float = 0.0 23 | thrust: float = 0.0 24 | delta_angle: float = 0.0 25 | 26 | 27 | @component 28 | class Health: 29 | max_hp: int 30 | hp: int = None 31 | 32 | 33 | @component 34 | class Perks: 35 | li_perks: Iterable[str] 36 | 37 | 38 | # ---------------------------------------- 39 | # ENTITIES 40 | # ---------------------------------------- 41 | @entity 42 | class Player(DirMobileBehavior, AvStyle, Health, MobPosition, Perks): # WARNING: order matters a lot! 43 | # You have to use the REVERSE order: 44 | # compos that hav only default values <<-- mixed compos <<-- compos that have only un-initialized values 45 | pass 46 | -------------------------------------------------------------------------------- /examples/ecs_naif/en_run.py: -------------------------------------------------------------------------------- 1 | import pyved_engine as pyv 2 | from demo_entities import Player 3 | from demo_systems import SysInput, SysEntityMover, SysView2D 4 | 5 | 6 | pyv.bootstrap_e() 7 | # global vars 8 | clock = None 9 | game_systems = pyv.SystemManager() 10 | 11 | 12 | def init_game(): 13 | global clock, game_systems 14 | pyv.init(mode=pyv.LOW_RES_MODE) #, maxfps=45, caption='my game (ECS fashion)') 15 | clock = pyv.vars.clock # vars.game_ticker 16 | 17 | # ----------------------- 18 | # Declare the pool of entities + all game systems 19 | # ----------------------- 20 | entity_pool = pyv.EntityManager() 21 | _player = Player( 22 | x=128, y=32, 23 | max_hp=125, 24 | li_perks=['toughGuy', 'kamikaze'], 25 | ) 26 | entity_pool.add(_player) 27 | 28 | game_systems.declare_systems([ # Instantiate all systems! 29 | SysInput(entity_pool), 30 | SysEntityMover(entity_pool), 31 | SysView2D(entity_pool, pyv.get_surface()) 32 | ]) 33 | 34 | 35 | def ecs_std_game_loop(): 36 | """ 37 | here's THE STANDARDIZED way to implement the game loop 38 | (it's in the procedural format) when using the ECS pattern... 39 | """ 40 | game_systems.init_all() 41 | while not game_systems['SysInput'].gameover: # the game loop per se 42 | game_systems.proc_all() 43 | pyv.flip() 44 | clock.tick(pyv.vars.max_fps) 45 | game_systems.cleanup_all() 46 | 47 | 48 | if __name__ == '__main__': 49 | print('Hint: Press SPACE to change the player gfx') 50 | init_game() 51 | ecs_std_game_loop() 52 | -------------------------------------------------------------------------------- /examples/ecs_naif/topdown-shooter-spritesheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/ecs_naif/topdown-shooter-spritesheet.png -------------------------------------------------------------------------------- /examples/immortalBundle/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/immortalBundle/__init__.py -------------------------------------------------------------------------------- /examples/immortalBundle/cartridge/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/immortalBundle/cartridge/__init__.py -------------------------------------------------------------------------------- /examples/immortalBundle/cartridge/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/immortalBundle/cartridge/bg.png -------------------------------------------------------------------------------- /examples/immortalBundle/cartridge/defeat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/immortalBundle/cartridge/defeat.png -------------------------------------------------------------------------------- /examples/immortalBundle/cartridge/immortal-magic.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/immortalBundle/cartridge/immortal-magic.wav -------------------------------------------------------------------------------- /examples/immortalBundle/cartridge/immortal-music.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/immortalBundle/cartridge/immortal-music.mp3 -------------------------------------------------------------------------------- /examples/immortalBundle/cartridge/immortal-sword.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/immortalBundle/cartridge/immortal-sword.wav -------------------------------------------------------------------------------- /examples/immortalBundle/cartridge/immortal-turok.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/immortalBundle/cartridge/immortal-turok.ttf -------------------------------------------------------------------------------- /examples/immortalBundle/cartridge/metadat.json: -------------------------------------------------------------------------------- 1 | { 2 | "vmlib_ver": "23_8a5", 3 | "dependencies": { 4 | "pyved_engine": "23.4a4" 5 | }, 6 | "description": "this is a placeholder for the name of your game", 7 | "author": "moonbak", 8 | "assets": [ 9 | "warrior-spritesheet.json", 10 | "sorc-spritesheet.json", 11 | "bg.png", 12 | "victory.png", 13 | "defeat.png", 14 | ["bigFont", "immortal-turok.ttf", 80], 15 | ["smaFont", "immortal-turok.ttf", 33] 16 | ], 17 | "sounds": [ 18 | "immortal-sword.wav", "immortal-magic.wav" 19 | ], 20 | "cartridge": "immortalBundle", 21 | "game_name": "Immortal", 22 | "build_date": "Fri Aug 25 17:22:49 2023" 23 | } -------------------------------------------------------------------------------- /examples/immortalBundle/cartridge/pimodules.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | upward_link = None 4 | 5 | 6 | def __getattr__(name): 7 | global upward_link 8 | # debug 9 | # print('pimodules is tryin to provide...', name) 10 | return upward_link[name] 11 | -------------------------------------------------------------------------------- /examples/immortalBundle/cartridge/sorc-spritesheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/immortalBundle/cartridge/sorc-spritesheet.png -------------------------------------------------------------------------------- /examples/immortalBundle/cartridge/victory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/immortalBundle/cartridge/victory.png -------------------------------------------------------------------------------- /examples/immortalBundle/cartridge/warrior-spritesheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/immortalBundle/cartridge/warrior-spritesheet.png -------------------------------------------------------------------------------- /examples/immortalBundle/vmslateL.py: -------------------------------------------------------------------------------- 1 | """ 2 | **Never edit that file!** 3 | 4 | Its part of the pyved_engine. 5 | 6 | The code below is standardized code (required to defined any GameBundleL), 7 | it helps in booting up the internal game cartridge (aka the PyvGC format) 8 | 9 | {{N.B. Tom }} 10 | In general its not recommanded to run that script directly, 11 | its way better to use `pyv-cli play GameBundleName` ... 12 | THAT BEING SAID, see the comment at the end of the file 13 | """ 14 | 15 | 16 | def bootgame(metadata): 17 | try: 18 | import vm 19 | rel_imports = False 20 | except ModuleNotFoundError: 21 | from . import vm 22 | rel_imports = True 23 | 24 | mon_inj = vm.Injector(None) 25 | mon_inj.set_lazy_loaded_module('pyved_engine', 'pyved_engine') 26 | mon_inj.set_lazy_loaded_module('math', 'math') 27 | vm.upward_link(mon_inj) 28 | 29 | if rel_imports: 30 | from .cartridge import pimodules 31 | pimodules.upward_link = mon_inj 32 | from .cartridge import gamedef 33 | vm.game_execution(metadata, gamedef) 34 | else: 35 | from cartridge import pimodules 36 | pimodules.upward_link = mon_inj 37 | from cartridge import gamedef 38 | vm.game_execution(metadata, gamedef) 39 | 40 | 41 | # I still keep the code below as its handy to allow the script direct execution in rare situations 42 | if __name__ == '__main__': 43 | import json 44 | with open('cartridge/metadat.json', 'r') as fp: 45 | bootgame(json.load(fp)) 46 | -------------------------------------------------------------------------------- /examples/isometric0/xassets/floor-tile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/isometric0/xassets/floor-tile.png -------------------------------------------------------------------------------- /examples/isometric0/xassets/half-floor-tile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/isometric0/xassets/half-floor-tile.png -------------------------------------------------------------------------------- /examples/isometric0/xassets/spritesheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/isometric0/xassets/spritesheet.png -------------------------------------------------------------------------------- /examples/isometric0/xassets/sync-tileset.json: -------------------------------------------------------------------------------- 1 | { "columns":3, 2 | "editorsettings": 3 | { 4 | "export": 5 | { 6 | "format":"json", 7 | "target":"sync-tileset.json" 8 | } 9 | }, 10 | "image":"spritesheet.png", 11 | "imageheight":144, 12 | "imagewidth":192, 13 | "margin":0, 14 | "name":"sync-tileset", 15 | "spacing":0, 16 | "tilecount":9, 17 | "tiledversion":"1.8.4", 18 | "tileheight":48, 19 | "tilewidth":64, 20 | "transformations": 21 | { 22 | "hflip":true, 23 | "preferuntransformed":false, 24 | "rotate":false, 25 | "vflip":false 26 | }, 27 | "transparentcolor":"#ff00ff", 28 | "type":"tileset", 29 | "version":"1.8" 30 | } -------------------------------------------------------------------------------- /examples/isometric0/xassets/sync-tileset.tsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/isometric0/xassets/sys_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/isometric0/xassets/sys_icon.png -------------------------------------------------------------------------------- /examples/isometric0/xassets/test_map.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | eJxjY2BgYANiTiTMRkNML3tw2U1vO0fxKB7Fo3gUDzwmVO/Qql4iZOZA1YcDFQcDFe/0tBtmHwAG3Q5N 11 | 12 | 13 | 14 | 15 | 16 | eJxjZmBgYGagPuAiQg0t7CXGThimt73I9Eixl552cw2Qveh2UcNeYvIPzK6BSs8DaS+9wUDZC7N7IOwcbvayAzErA0MDPrtpAVhpZO4oGNyACYgBexQBEg== 17 | 18 | 19 | 20 | 21 | eJxjYKAN4KKRudQCjKP2Dju70dPcUA5rUvPPUPbrKBicgGnU3lEwCsgGoPQEACY7AC8= 22 | 23 | 24 | 25 | 26 | eJxjYKAN4KKRuaNgFOACwynNDSe/jIJRMBQAy0A7YBQMK8AExADooAAl 27 | 28 | 29 | 30 | 31 | eJxjYKAN4KKRuaNgFOACwynNDSe/jIJRMApGwUgEAN9IAB8= 32 | 33 | 34 | 35 | 36 | eJxjYKAN4KKRuaNgFOACwynNDSe/jIJRMApGwUgEAN9IAB8= 37 | 38 | 39 | 40 | 41 | eJxjYKAN4KKRuaNgFOACwynNDSe/jIJRMApGwUgEAN9IAB8= 42 | 43 | 44 | 45 | 46 | eJxjYKAN4KKRuaNgFOACwynNDSe/jIJRMApGwUgEAN9IAB8= 47 | 48 | 49 | 50 | 51 | eJxjYKAN4KKRuaNgFOACwynNDSe/jIJRMApGwUgEAN9IAB8= 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /examples/isometric0/xassets/test_map2.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | eJwTYmBgEAJiTiQsRCHmR6L50eSoaQ8+u7FhWtk5iomPg6FmJzHmUttufhqZO1jjbhSPYnpgQvUOreolQmbSsj7EhQeqbMHWJhgu9vJjwQBrPilu 11 | 12 | 13 | 14 | 15 | 16 | eJzt08EKwCAMA9AwkZ37x376vBREGIvDNeAMBA8tvItNABLmx4idL1zG9Ea77fsXN9I2kdtbM1zmftxS/WelGx2V67bCXM09azNQ7ubMzVlTNnlg98l74+9octReTgIBzg== 17 | 18 | 19 | 20 | 21 | eJxjYKANEKSRudQCjKP2Dju70dPcUA5rUvPPUPbrKBicYKDK8JFm7ygYnoAJiAE54gBx 22 | 23 | 24 | 25 | 26 | eJxjYKANEKSRuaNgFOACwynNDSe/jIJRMBTAaJ4bBdQETEAMAJyvAEc= 27 | 28 | 29 | 30 | 31 | eJxjYKAN4KaRuaNgFOACo2luFIyCUTAKRsFgAQC1FAAX 32 | 33 | 34 | 35 | 36 | eJxjYKAN4KaRuaNgFOACo2luFIyCUTAKRsFgAQC1FAAX 37 | 38 | 39 | 40 | 41 | eJxjYBgFo2B4AO6BdsAoGAWjYBSMglEABQBRvAAM 42 | 43 | 44 | 45 | 46 | eJxjYBgFo2B4AO6BdsAoGAWjYBSMglEABQBRvAAM 47 | 48 | 49 | 50 | 51 | eJztwTEBAAAAwqD1T20JT6AAAHgaCWAAAQ== 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /examples/platformer0/assets/enemy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/platformer0/assets/enemy.png -------------------------------------------------------------------------------- /examples/platformer0/assets/info-asset-license.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | Avatar - https://opengameart.org/content/blocky 4 | by Zack Alvarado 5 | 6 | Tileset - https://opengameart.org/content/free-platformer-game-tileset 7 | by pzUH 8 | 9 | background - https://opengameart.org/content/magic-cliffs-environment 10 | by Luis Zuno (@ansimuz) 11 | 12 | 13 | A few other assets were taken come from a browser game called 14 | "Wizard With Cane In Purple Mantle Goes On Journey" 15 | that is freely available on the web. 16 | Most assets in the game are probably copyright free, 17 | but I cannot be 100% 18 | the "Wizard With Cane In Purple Mantle Goes On Journey" 19 | does not display Credits or author information! 20 | 21 | Use with care or simply replace assets from unknown origin with your own. 22 | -------------------------------------------------------------------------------- /examples/platformer0/assets/missile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/platformer0/assets/missile.png -------------------------------------------------------------------------------- /examples/platformer0/assets/player-left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/platformer0/assets/player-left.png -------------------------------------------------------------------------------- /examples/platformer0/assets/player-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/platformer0/assets/player-right.png -------------------------------------------------------------------------------- /examples/platformer0/assets/tiledbackground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/platformer0/assets/tiledbackground.png -------------------------------------------------------------------------------- /examples/platformer0/assets/tilemap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/platformer0/assets/tilemap.png -------------------------------------------------------------------------------- /examples/platformer0/tiles.tsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /examples/poker_uth/pokerbundle/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/poker_uth/pokerbundle/__init__.py -------------------------------------------------------------------------------- /examples/poker_uth/pokerbundle/common.py: -------------------------------------------------------------------------------- 1 | #import katagames_sdk as katasdk 2 | import pyved_engine as pyv 3 | #katasdk.bootstrap() 4 | #kengi = katasdk.kengi 5 | kengi= pyv 6 | 7 | refgame, refmodel, refview = None, None, None 8 | 9 | 10 | def chip_scrolldown(x): 11 | global refmodel 12 | omega = (2, 5, 10, 20) 13 | curridx = omega.index(x) 14 | curridx -= 1 15 | if curridx < 0: 16 | curridx = len(omega) - 1 17 | y = omega[curridx] 18 | refmodel.set_chipvalue(y) 19 | 20 | 21 | def chip_scrollup(x): 22 | global refmodel 23 | omega = (2, 5, 10, 20) 24 | curridx = omega.index(x) 25 | curridx = (curridx + 1) % len(omega) 26 | y = omega[curridx] 27 | refmodel.set_chipvalue(y) 28 | 29 | 30 | PokerStates = kengi.e_struct.enum( 31 | 'AnteSelection', 32 | 'PreFlop', 33 | 'Flop', 34 | 'TurnRiver', 35 | 'Outcome' 36 | ) 37 | 38 | MyEvTypes = kengi.game_events_enum(( 39 | 'StackChip', # used to bet in an incremental way, contains: trips(True/False) 40 | 'CycleChipval', # contains: upwards(int: 1 or 0), to answer 'do we cycle 2->5->10->... or the other way around?' 41 | 42 | # - IMPACT from buttons in AnteSelectionState 43 | 'DealCards', # this litteraly means ->clicking the Start button... In AnteSelection stage 44 | 'BetIdem', 45 | 'BetUndo', 46 | 'BetReset', 47 | 48 | # - IMPACT from buttons (generic) 49 | 'BetDecision', 50 | 'BetHighDecision', # can be sent only from the PreFlopState 51 | 'CheckDecision', # can also represent a FOLD operation (at the TurnRiverState) 52 | 53 | 'NewMatch', 54 | 'MoneyUpdate', # contains: ante, bet, play, trips, wealth 55 | 'ChipUpdate', # contains: value 56 | 'StateChanges', # contains: pokerstate 57 | 'RienNeVaPlus', # sent when player has chosen bet or fold 58 | 'MatchOver', # contains: won(-1, 0, +1) 59 | )) 60 | -------------------------------------------------------------------------------- /examples/poker_uth/user_assets/capello-ft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/poker_uth/user_assets/capello-ft.png -------------------------------------------------------------------------------- /examples/poker_uth/user_assets/overlay0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/poker_uth/user_assets/overlay0.png -------------------------------------------------------------------------------- /examples/poker_uth/user_assets/pokerbackground3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/poker_uth/user_assets/pokerbackground3.png -------------------------------------------------------------------------------- /examples/poker_uth/user_assets/pokerchips.json: -------------------------------------------------------------------------------- 1 | { 2 | "frames": [ 3 | { 4 | "filename": "chip02.png", 5 | "frame": { 6 | "x": 0, 7 | "y": 0, 8 | "w": 62, 9 | "h": 62 10 | }, 11 | "rotated": false, 12 | "trimmed": false, 13 | "spriteSourceSize": { 14 | "x": 0, 15 | "y": 0, 16 | "w": 62, 17 | "h": 62 18 | }, 19 | "sourceSize": { 20 | "w": 62, 21 | "h": 62 22 | } 23 | }, 24 | { 25 | "filename": "chip05.png", 26 | "frame": { 27 | "x": 62, 28 | "y": 0, 29 | "w": 62, 30 | "h": 62 31 | }, 32 | "rotated": false, 33 | "trimmed": false, 34 | "spriteSourceSize": { 35 | "x": 0, 36 | "y": 0, 37 | "w": 62, 38 | "h": 62 39 | }, 40 | "sourceSize": { 41 | "w": 62, 42 | "h": 62 43 | } 44 | }, 45 | { 46 | "filename": "chip10.png", 47 | "frame": { 48 | "x": 124, 49 | "y": 0, 50 | "w": 62, 51 | "h": 62 52 | }, 53 | "rotated": false, 54 | "trimmed": false, 55 | "spriteSourceSize": { 56 | "x": 0, 57 | "y": 0, 58 | "w": 62, 59 | "h": 62 60 | }, 61 | "sourceSize": { 62 | "w": 62, 63 | "h": 62 64 | } 65 | }, 66 | { 67 | "filename": "chip20.png", 68 | "frame": { 69 | "x": 186, 70 | "y": 0, 71 | "w": 62, 72 | "h": 62 73 | }, 74 | "rotated": false, 75 | "trimmed": false, 76 | "spriteSourceSize": { 77 | "x": 0, 78 | "y": 0, 79 | "w": 62, 80 | "h": 62 81 | }, 82 | "sourceSize": { 83 | "w": 62, 84 | "h": 62 85 | } 86 | } 87 | ], 88 | "meta": { 89 | "app": "http://www.codeandweb.com/texturepacker", 90 | "version": "1.0", 91 | "image": "spritesheet.png", 92 | "format": "RGBA8888", 93 | "size": { 94 | "w": 248, 95 | "h": 62 96 | }, 97 | "scale": "1" 98 | } 99 | } -------------------------------------------------------------------------------- /examples/poker_uth/user_assets/pokerchips.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/poker_uth/user_assets/pokerchips.png -------------------------------------------------------------------------------- /examples/poker_uth/user_assets/pxart-french-cards.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/poker_uth/user_assets/pxart-french-cards.png -------------------------------------------------------------------------------- /examples/protoAsteroBundle/dummylib.py: -------------------------------------------------------------------------------- 1 | 2 | print('hello this is dummylib!') 3 | -------------------------------------------------------------------------------- /examples/protoAsteroBundle/dummylib2.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | print('hayo! Dummylib 2 is ready') 4 | -------------------------------------------------------------------------------- /examples/protoAsteroBundle/shooter.py: -------------------------------------------------------------------------------- 1 | from .vectorsprites import * 2 | from .soundManager import * 3 | 4 | 5 | class Shooter(VectorSprite): 6 | 7 | def __init__(self, position, heading, pointlist, stage): 8 | VectorSprite.__init__(self, position, heading, pointlist, (255,255,255)) 9 | self.bullets = [] 10 | self.stage = stage 11 | 12 | def fire_bullet(self, heading, ttl, velocity, shoot_sound): 13 | if (len(self.bullets) < self.maxBullets): 14 | position = Vector2d(self.position.x, self.position.y) 15 | newBullet = Bullet(position, heading, self, ttl, velocity, self.stage) 16 | self.bullets.append(newBullet) 17 | self.stage.add_sprite(newBullet) 18 | play_sound(shoot_sound) 19 | 20 | def bullet_collision(self, target): 21 | collisionDetected = False 22 | for bullet in self.bullets: 23 | if bullet.ttl > 0 and target.collidesWith(bullet): 24 | collisionDetected = True 25 | bullet.ttl = 0 26 | 27 | return collisionDetected 28 | 29 | class Bullet(Point): 30 | 31 | def __init__(self, position, heading, shooter, ttl, velocity, stage): 32 | Point.__init__(self, position, heading, stage) 33 | self.shooter = shooter 34 | self.ttl = ttl 35 | self.velocity = velocity 36 | 37 | def move(self): 38 | Point.move(self) 39 | if (self.ttl <= 0): 40 | self.shooter.bullets.remove(self) 41 | -------------------------------------------------------------------------------- /examples/protoAsteroBundle/soundManager.py: -------------------------------------------------------------------------------- 1 | 2 | from . import vars 3 | 4 | katasdk = vars.katasdk 5 | pygame = katasdk.kengi.pygame 6 | 7 | 8 | # from pygame.locals import * 9 | 10 | sounds = {} 11 | 12 | PREF = 'user_assets/astero-' 13 | 14 | 15 | def init_sound_manager(): 16 | pygame.mixer.init() 17 | sounds["fire"] = pygame.mixer.Sound(PREF+"FIRE.WAV") 18 | sounds["explode1"] = pygame.mixer.Sound(PREF+"EXPLODE1.WAV") 19 | sounds["explode2"] = pygame.mixer.Sound(PREF+"EXPLODE2.WAV") 20 | sounds["explode3"] = pygame.mixer.Sound(PREF+"EXPLODE3.WAV") 21 | sounds["lsaucer"] = pygame.mixer.Sound(PREF+"LSAUCER.WAV") 22 | sounds["ssaucer"] = pygame.mixer.Sound(PREF+"SSAUCER.WAV") 23 | sounds["thrust"] = pygame.mixer.Sound(PREF+"THRUST.WAV") 24 | sounds["sfire"] = pygame.mixer.Sound(PREF+"SFIRE.WAV") 25 | sounds["extralife"] = pygame.mixer.Sound(PREF+"LIFE.WAV") 26 | 27 | def play_sound(soundName): 28 | channel = sounds[soundName].play() 29 | 30 | def play_sound_continuous(soundName): 31 | channel = sounds[soundName].play(-1) 32 | 33 | def stop_sound(soundName): 34 | channel = sounds[soundName].stop() 35 | -------------------------------------------------------------------------------- /examples/survival/assets/(zombie)bonus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/(zombie)bonus.png -------------------------------------------------------------------------------- /examples/survival/assets/(zombie)bullet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/(zombie)bullet.png -------------------------------------------------------------------------------- /examples/survival/assets/(zombie)cell_tower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/(zombie)cell_tower.png -------------------------------------------------------------------------------- /examples/survival/assets/(zombie)comms_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/(zombie)comms_icon.png -------------------------------------------------------------------------------- /examples/survival/assets/(zombie)health_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/(zombie)health_icon.png -------------------------------------------------------------------------------- /examples/survival/assets/(zombie)hitman_gun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/(zombie)hitman_gun.png -------------------------------------------------------------------------------- /examples/survival/assets/(zombie)landmine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/(zombie)landmine.png -------------------------------------------------------------------------------- /examples/survival/assets/(zombie)light_350_med.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/(zombie)light_350_med.png -------------------------------------------------------------------------------- /examples/survival/assets/(zombie)manBlue_gun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/(zombie)manBlue_gun.png -------------------------------------------------------------------------------- /examples/survival/assets/(zombie)mine_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/(zombie)mine_icon.png -------------------------------------------------------------------------------- /examples/survival/assets/(zombie)pistol.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/(zombie)pistol.png -------------------------------------------------------------------------------- /examples/survival/assets/(zombie)pistol_ammo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/(zombie)pistol_ammo.png -------------------------------------------------------------------------------- /examples/survival/assets/(zombie)shotgun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/(zombie)shotgun.png -------------------------------------------------------------------------------- /examples/survival/assets/(zombie)shotgun_ammo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/(zombie)shotgun_ammo.png -------------------------------------------------------------------------------- /examples/survival/assets/(zombie)uzi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/(zombie)uzi.png -------------------------------------------------------------------------------- /examples/survival/assets/(zombie)uzi_ammo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/(zombie)uzi_ammo.png -------------------------------------------------------------------------------- /examples/survival/assets/(zombies)explosion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/(zombies)explosion.png -------------------------------------------------------------------------------- /examples/survival/assets/(zombies)tile_179.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/(zombies)tile_179.png -------------------------------------------------------------------------------- /examples/survival/assets/(zombies)whitePuff15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/(zombies)whitePuff15.png -------------------------------------------------------------------------------- /examples/survival/assets/(zombies)whitePuff16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/(zombies)whitePuff16.png -------------------------------------------------------------------------------- /examples/survival/assets/(zombies)whitePuff17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/(zombies)whitePuff17.png -------------------------------------------------------------------------------- /examples/survival/assets/(zombies)whitePuff18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/(zombies)whitePuff18.png -------------------------------------------------------------------------------- /examples/survival/assets/(zombies)xxORGxxexplosion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/(zombies)xxORGxxexplosion.png -------------------------------------------------------------------------------- /examples/survival/assets/DemonSker-zyzD.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/DemonSker-zyzD.ttf -------------------------------------------------------------------------------- /examples/survival/assets/blood-splatter1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/blood-splatter1.png -------------------------------------------------------------------------------- /examples/survival/assets/blood-splatter2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/blood-splatter2.png -------------------------------------------------------------------------------- /examples/survival/assets/blood-splatter3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/blood-splatter3.png -------------------------------------------------------------------------------- /examples/survival/assets/blood-splatter4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/blood-splatter4.png -------------------------------------------------------------------------------- /examples/survival/assets/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/icons.png -------------------------------------------------------------------------------- /examples/survival/assets/light_350_hard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/light_350_hard.png -------------------------------------------------------------------------------- /examples/survival/assets/light_350_soft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/light_350_soft.png -------------------------------------------------------------------------------- /examples/survival/assets/light_radius.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/light_radius.png -------------------------------------------------------------------------------- /examples/survival/assets/shotgun_ammo_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/shotgun_ammo_icon.png -------------------------------------------------------------------------------- /examples/survival/assets/snd/10.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/10.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/11.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/11.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/12.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/12.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/13.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/13.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/14.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/14.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/1beep.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/1beep.mp3 -------------------------------------------------------------------------------- /examples/survival/assets/snd/8.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/8.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/9.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/9.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/City-of-the-Disturbed.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/City-of-the-Disturbed.ogg -------------------------------------------------------------------------------- /examples/survival/assets/snd/ammo_pickup.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/ammo_pickup.ogg -------------------------------------------------------------------------------- /examples/survival/assets/snd/brains2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/brains2.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/brains3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/brains3.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/chiptronic.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/chiptronic.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/drop_sound.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/drop_sound.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/empty_gun.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/empty_gun.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/espionage.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/espionage.ogg -------------------------------------------------------------------------------- /examples/survival/assets/snd/explo_basique.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/explo_basique.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/gun_pickup.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/gun_pickup.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/item_pickup.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/item_pickup.ogg -------------------------------------------------------------------------------- /examples/survival/assets/snd/level_start.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/level_start.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/pistol.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/pistol.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/short_explosion.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/short_explosion.ogg -------------------------------------------------------------------------------- /examples/survival/assets/snd/shotgun.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/shotgun.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/splat-15.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/splat-15.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/uzi.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/uzi.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/zombie-roar-1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/zombie-roar-1.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/zombie-roar-2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/zombie-roar-2.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/zombie-roar-3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/zombie-roar-3.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/zombie-roar-4.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/zombie-roar-4.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/zombie-roar-5.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/zombie-roar-5.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/zombie-roar-6.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/zombie-roar-6.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/zombie-roar-7.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/zombie-roar-7.wav -------------------------------------------------------------------------------- /examples/survival/assets/snd/zombie-roar-8.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/snd/zombie-roar-8.wav -------------------------------------------------------------------------------- /examples/survival/assets/spritesheet_tiles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/spritesheet_tiles.png -------------------------------------------------------------------------------- /examples/survival/assets/zombie1_hold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/zombie1_hold.png -------------------------------------------------------------------------------- /examples/survival/assets/zombie2_hold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival/assets/zombie2_hold.png -------------------------------------------------------------------------------- /examples/survival_c/game.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | import pyved_engine as pyv 4 | import shared 5 | import systems 6 | 7 | 8 | @pyv.declare_begin 9 | def prep_zombiegame(vmst=None): 10 | pyv.init() 11 | 12 | pyv.define_archetype("Zombie", ["Position2d", "Health", "Color"]) 13 | pyv.define_archetype("Player", ["Position2d", "Speed", "Gun", "Gfx"]) 14 | 15 | # Create zombies 16 | zombies = [None] * shared.NZ 17 | for i in range(shared.NZ): 18 | zombies[i] = pyv.new_from_archetype("Zombie") 19 | pyv.init_entity( 20 | zombies[i], 21 | { 22 | "Position2d": (random.randint(100, 700), random.randint(100, 500)), 23 | "Health": random.randint(50, 100), 24 | "Color": [random.randint(0, 255) for _ in range(3)] 25 | } 26 | ) 27 | 28 | # Create player 29 | player = pyv.new_from_archetype("Player") 30 | pyv.init_entity( 31 | player, 32 | { 33 | "Position2d": (400, 300), 34 | "Speed": [0, 0], 35 | "Gun": { 36 | "dAngle": 0.0, 37 | "Angle": 0, 38 | "Damage": 10 39 | }, 40 | "Gfx": { 41 | "Style": 0, 42 | "Spritesheet": pyv.load_spritesheet('topdown-shooter-spritesheet.png', (32, 32), ck='black') 43 | } 44 | } 45 | ) 46 | pyv.bulk_add_systems(systems) # get any system found in module 'systems', add it to the ECS manager 47 | 48 | 49 | @pyv.declare_update 50 | def maj_zombiegame(into_t): 51 | for event in pyv.fetch_events(): 52 | if event.type == pyv.pygame.QUIT: 53 | pyv.vars.gameover = True 54 | pyv.systems_proc() # run everything described in systems 55 | 56 | 57 | @pyv.declare_end 58 | def zombie_gameover(vmst=None): 59 | pyv.close_game() 60 | 61 | 62 | if __name__ == '__main__': 63 | pyv.run_game() 64 | -------------------------------------------------------------------------------- /examples/survival_c/shared.py: -------------------------------------------------------------------------------- 1 | """ 2 | constants and variables shared by different systems 3 | """ 4 | 5 | NZ = 13 # nb of zombies 6 | NB_STYLES = 4 # styles for the avatar 7 | space_pressed = False # used by the input system 8 | -------------------------------------------------------------------------------- /examples/survival_c/topdown-shooter-spritesheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/survival_c/topdown-shooter-spritesheet.png -------------------------------------------------------------------------------- /examples/tmx_testing/level.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | eJztlX1OwkAQxQf8QMRLWEVFuIS2MRq9hND4D5zDc/s2dNIJbux+tHRj5yW/NDTb2dk3OwORSqVSqVQqlUql+s+agAswA1c955KaUvNmNkIeo76z6Ff34AEswarnXFJTat4scVdXA7uv5rhjcOK4PrUZ06VS9ob3moLLI+3pq7EF4+VpQCyuxTXIwI3jd6nNGNbQvOG9FuDRcc9j3XH2L7NgvLwNiOVbi1Q1BG/knD+PiBNyx0PE/j2DHBTVMxe/bbPFNmtSq0WshuCNzOuuYW3oDJU9EYPx8Yn29ViDDSirp4FrktHvOmXifSHoWk2eqTd+98mckXN/aVgbOkNlT8Rg/s8+aV8PWZOS7PMkt7yX35TUfV2aPFNv7N7IPja9eAZewZvI9wu8t8wH1X1v88uHoorDcF3kms0BLjFjz6fetO+N7GPTi3NLft9g2zI7qvv+0C9fSqrnx/qPmHJGuMSMPZ960743P3SspbU= 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /examples/tmx_testing/main.py: -------------------------------------------------------------------------------- 1 | 2 | import katagames_engine as kengi 3 | kengi.bootstrap_e() 4 | 5 | # - aliases 6 | pygame = kengi.pygame 7 | tmx = kengi.tmx.misc 8 | tmxdata = kengi.tmx.data 9 | 10 | #SCR_SIZE = (640, 480) 11 | OFFSET = 5 12 | dj, di = 0, 0 # variation 13 | stop_the_test = False 14 | 15 | kengi.init(2) 16 | 17 | clock = pygame.time.Clock() 18 | #scr = pygame.display.set_mode(SCR_SIZE) 19 | scr=kengi.get_surface() 20 | scr_size = scr.get_size() 21 | 22 | tm_obj = tmxdata.load_tmx('level.tmx') 23 | 24 | # - debug infos 25 | print(tm_obj.layers['set'], tm_obj.layers['triggers']) 26 | 27 | print('------ testing TMX loading, TMX-based display ------') 28 | print('use arrow keys to move viewport') 29 | 30 | # init viewport 31 | viewport = tmx.Viewport(tm_obj, (0, 0), scr_size) 32 | viewport.force_focus(288, 240) 33 | 34 | i, j = viewport.center # since viewport was auto. init by constructor 35 | print('initial i j values= ', i, j) 36 | 37 | bg = None 38 | if tm_obj.background: 39 | print('bg found') 40 | 41 | # turn background image to a sprite, so we can repeat it easily 42 | bg = pygame.sprite.Sprite() 43 | bg.image = pygame.image.load(tm_obj.background['img_path']) 44 | bg.rect = bg.image.get_rect() 45 | 46 | bg.rect.left = -16 + tm_obj.background['offsetx'] 47 | bg.rect.top = 0 48 | print(bg.rect.topleft) 49 | 50 | while not stop_the_test: 51 | for ev in pygame.event.get(): 52 | if ev.type == pygame.QUIT: 53 | stop_the_test = True 54 | elif ev.type == pygame.KEYDOWN: 55 | if ev.key == pygame.K_LEFT: 56 | di = -OFFSET 57 | elif ev.key == pygame.K_RIGHT: 58 | di = +OFFSET 59 | elif ev.key == pygame.K_DOWN: 60 | dj = +OFFSET 61 | elif ev.key == pygame.K_UP: 62 | dj = -OFFSET 63 | elif ev.type == pygame.KEYUP: 64 | pkeys = pygame.key.get_pressed() 65 | if (not pkeys[pygame.K_DOWN]) and (not pkeys[pygame.K_UP]): 66 | dj = 0 67 | if (not pkeys[pygame.K_LEFT]) and (not pkeys[pygame.K_RIGHT]): 68 | di = 0 69 | 70 | if dj != 0 or di != 0: 71 | i += di 72 | j += dj 73 | viewport.set_focus(i, j) 74 | i, j = viewport.center 75 | #viewport.force_focus(i, j) 76 | 77 | # manually blit the bg ... 78 | # scr.fill((0, 0, 0)) 79 | scr.blit(bg.image, bg.rect.topleft) 80 | 81 | viewport.draw(scr) 82 | # pygame.display.flip() 83 | kengi.flip() 84 | clock.tick(50) 85 | 86 | print('bye!') 87 | kengi.quit() 88 | -------------------------------------------------------------------------------- /examples/tmx_testing/tiledbackground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/tmx_testing/tiledbackground.png -------------------------------------------------------------------------------- /examples/tmx_testing/tilemap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples/tmx_testing/tilemap.png -------------------------------------------------------------------------------- /examples/tmx_testing/tiles.tsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /examples_basic/demo-a-kengi-straightf.py: -------------------------------------------------------------------------------- 1 | import pyved_engine as pyv 2 | 3 | 4 | # constants 5 | BG_COLOR = 'antiquewhite2' 6 | COLOR_PALETTE = { 7 | 0: (244, 105, 251), 8 | 1: (105, 184, 251) 9 | } 10 | 11 | 12 | class SharedVars: 13 | def __init__(self): 14 | self.game_over = False 15 | self.av_y_speed = 0 16 | self.curr_color_code = 0 17 | 18 | 19 | def event_handling(ev_queue, state): 20 | pygame = pyv.pygame 21 | for ev in ev_queue: 22 | if ev.type == pygame.QUIT: 23 | state.game_over = True 24 | 25 | elif ev.type == pyv.pygame.KEYDOWN: 26 | if ev.key == pygame.K_ESCAPE: 27 | state.game_over = True 28 | elif ev.key == pygame.K_SPACE: 29 | state.curr_color_code = (state.curr_color_code + 1) % 2 30 | elif ev.key == pygame.K_UP: 31 | state.av_y_speed = -1 32 | elif ev.key == pygame.K_DOWN: 33 | state.av_y_speed = 1 34 | 35 | elif ev.type == pygame.KEYUP: 36 | prkeys = pygame.key.get_pressed() 37 | if (not prkeys[pygame.K_UP]) and (not prkeys[pygame.K_DOWN]): 38 | state.av_y_speed = 0 39 | 40 | 41 | def play_game(): 42 | # ------------------- 43 | # demo STyle 1 44 | # ------------------- 45 | pyv.init(2, caption='demo-a uses kengi / straightforward variant') 46 | 47 | av_pos = [240, 135] 48 | game_st = SharedVars() 49 | screen = pyv.get_surface() 50 | scr_size = screen.get_size() 51 | clock = pyv.vars.game_ticker # pre-defined Clock in the pyved_engine!! 52 | 53 | while not game_st.game_over: # <----- my own game loop 54 | 55 | event_handling(pyv.pygame.event.get(), game_st) 56 | av_pos[1] = (av_pos[1] + game_st.av_y_speed) % scr_size[1] 57 | screen.fill(BG_COLOR) 58 | pl_color = COLOR_PALETTE[game_st.curr_color_code] 59 | pyv.draw_circle(screen, pl_color, av_pos, 15, 0) 60 | pyv.flip() 61 | clock.tick(60) 62 | 63 | 64 | """ 65 | Right now (June 2023), there are 3 ways to define your game: 66 | 67 | 1/ use any event system you like(the new one, or pygame legacy event system) + define your own game loop 68 | 2/ use the new event system + objects from Pyv that can post/subscribe to events 69 | 3/ use the pyv.GameTpl and redefine the .get_video_mode() method 70 | """ 71 | 72 | if __name__ == '__main__': 73 | print(" Pyved_engine straightforward variant of ~~~ Demo A | controls:") 74 | print("UP/DOWN arrow, SPACE, ESCAPE") 75 | play_game() 76 | pyv.close_game() 77 | print('bye.') 78 | -------------------------------------------------------------------------------- /examples_basic/demo-a-pygame.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | 3 | 4 | # constants 5 | BG_COLOR = 'antiquewhite2' 6 | COLOR_PALETTE = { 7 | 0: (244, 105, 251), 8 | 1: (105, 184, 251) 9 | } 10 | SCR_SIZE = (480, 270) 11 | 12 | 13 | class SharedVars: 14 | def __init__(self): 15 | self.game_over = False 16 | self.av_y_speed = 0 17 | self.curr_color_code = 0 18 | 19 | 20 | def event_handling(ev_queue, state): 21 | for ev in ev_queue: 22 | if ev.type == pygame.QUIT: 23 | state.game_over = True 24 | 25 | elif ev.type == pygame.KEYDOWN: 26 | if ev.key == pygame.K_ESCAPE: 27 | state.game_over = True 28 | elif ev.key == pygame.K_SPACE: 29 | state.curr_color_code = (state.curr_color_code + 1) % 2 30 | elif ev.key == pygame.K_UP: 31 | state.av_y_speed = -1 32 | elif ev.key == pygame.K_DOWN: 33 | state.av_y_speed = 1 34 | 35 | elif ev.type == pygame.KEYUP: 36 | prkeys = pygame.key.get_pressed() 37 | if (not prkeys[pygame.K_UP]) and (not prkeys[pygame.K_DOWN]): 38 | state.av_y_speed = 0 39 | 40 | 41 | def play_game(): 42 | av_pos = [240, 135] 43 | game_st = SharedVars() 44 | screen = pygame.display.set_mode(SCR_SIZE) 45 | clock = pygame.time.Clock() 46 | 47 | while not game_st.game_over: 48 | event_handling(pygame.event.get(), game_st) 49 | 50 | av_pos[1] = (av_pos[1] + game_st.av_y_speed) % SCR_SIZE[1] 51 | 52 | screen.fill(BG_COLOR) 53 | pl_color = COLOR_PALETTE[game_st.curr_color_code] 54 | pygame.draw.circle(screen, pl_color, av_pos, 15, 0) 55 | pygame.display.update() 56 | clock.tick(60) 57 | 58 | 59 | if __name__ == '__main__': 60 | print("Demo A | controls:") 61 | print("UP/DOWN arrow, SPACE, ESCAPE") 62 | pygame.init() 63 | pygame.display.set_caption('demo-a uses pygame only') 64 | play_game() 65 | pygame.quit() 66 | print('bye.') 67 | -------------------------------------------------------------------------------- /examples_basic/demo-ascii.py: -------------------------------------------------------------------------------- 1 | import pyved_engine as pyv 2 | 3 | 4 | pyv.bootstrap_e() 5 | 6 | # - const 7 | CAR_SIZE = 12 # 20, 16, 12, 10, 8 vont fonctionner si c'est le mode HD de pyv qui est actif 8 | 9 | IDX_CURSOR = 254 10 | MAXFPS = 50 11 | Y_PAL_POS = 15 12 | PAL = pyv.pal.c64 13 | 14 | # - variables 15 | pygame = pyv.pygame 16 | ajouts = dict() 17 | asc_canvas = canv_bsupx = canv_bsupy = None 18 | 19 | gameover = False 20 | text_pos = None 21 | tpos = [0, 0] 22 | 23 | _scr = None 24 | 25 | 26 | # -- before starting the main program 27 | def init_game(): 28 | global _scr, asc_canvas, canv_bsupx, canv_bsupy 29 | pyv.init() # pyv.LOW_RES_MODE) 30 | asc_canvas = pyv.ascii 31 | asc_canvas.init(CAR_SIZE) 32 | canv_bsupx, canv_bsupy = asc_canvas.get_bounds() 33 | _scr = pyv.get_surface() 34 | 35 | 36 | def game_loop(): 37 | global asc_canvas 38 | while not pyv.vars.gameover: 39 | for ev in pyv.evsys0.get(): 40 | if ev.type == pygame.QUIT or (ev.type == pygame.KEYDOWN and ev.key == pygame.K_ESCAPE): 41 | pyv.vars.gameover = True 42 | elif ev.type == pygame.MOUSEBUTTONDOWN: 43 | text_pos = list(pyv.ascii.screen_to_cpos(ev.pos)) 44 | elif ev.type == pygame.KEYDOWN: 45 | 46 | if ev.key == pygame.K_BACKSPACE: 47 | pyv.ascii.increm_char_size() 48 | text_pos = None 49 | 50 | elif text_pos is not None and ev.key != pygame.K_RETURN: 51 | cle = tuple(text_pos) 52 | if cle not in ajouts: 53 | ajouts[cle] = list() 54 | if len(ev.unicode) == 1: 55 | ajouts[cle].append(ev.unicode) 56 | 57 | _scr.fill(PAL['blue']) 58 | # pp = vscreen pygame.mouse.get_pos() 59 | pp = pyv.get_mouse_coords() 60 | p = list(asc_canvas.screen_to_cpos(pp)) 61 | 62 | # draw the tileset 63 | for i in range(ord('0'), ord('Z')): 64 | tpos[0] = (i % 16) 65 | tpos[1] = (i // 16) 66 | asc_canvas.put_char(chr(i), tpos, PAL['lightblue']) 67 | 68 | # draw palette 69 | cf = pyv.ascii.CODE_FILL 70 | for i in range(16): 71 | asc_canvas.put_char(cf, (i, Y_PAL_POS), PAL[i]) 72 | asc_canvas.put_char(cf, (i, Y_PAL_POS+1), PAL[i]) 73 | asc_canvas.put_char(cf, (i, Y_PAL_POS+2), PAL[i]) 74 | 75 | for adhoc_tpos, aj in ajouts.items(): 76 | if len(aj): 77 | tmp_pos = list(adhoc_tpos) 78 | for e in list(aj): # letter one by one 79 | tmp = asc_canvas.put_char(e, tmp_pos, PAL[3], PAL['darkgrey']) 80 | tmp_pos[0] += 1 81 | 82 | # draw the cursor 83 | gvpos = [ 84 | (p[0] - 1, p[1] - 1), 85 | (p[0] + 1, p[1] - 1), 86 | (p[0] - 1, p[1] + 1), 87 | (p[0] + 1, p[1] + 1), 88 | ] 89 | for elt in ((True, gvpos[0]), (True, gvpos[-1]), (False, gvpos[1]), (False, gvpos[2])): 90 | flag, popo = elt 91 | car = '\\' if flag else '/' 92 | if asc_canvas.is_inside(popo): 93 | asc_canvas.put_char(car, popo, (250, 11, 33)) 94 | 95 | pyv.flip() # already using the .tick to cap the framerate 96 | 97 | 98 | if __name__ == '__main__': 99 | print('running tests (pyv.ascii)') 100 | init_game() 101 | game_loop() 102 | pyv.quit() 103 | -------------------------------------------------------------------------------- /examples_basic/imgfont-creat-helper.py: -------------------------------------------------------------------------------- 1 | """ 2 | this file can help to convert TTF-based fonts to image-based fonts, 3 | can be handy for various projects when attempting to port the game 4 | so it runs nicely in the web context 5 | """ 6 | import pyved_engine as pyv 7 | 8 | 9 | pyv.init(pyv.RETRO_MODE) 10 | pygame = pyv.pygame 11 | screen = pyv.get_surface() 12 | width, height = screen.get_size() 13 | FT_PATH = 'mixed_assets/alphbeta.ttf' 14 | pyg_font = pygame.font.Font(FT_PATH, 12) 15 | 16 | block = pyv.gui.TextBlock( 17 | pyg_font, 'no text', (255, 0, 0) # pick either pyg_font or custom_ft 18 | ) 19 | block.text_align = 0 # here, 0 means: left aligned text 20 | 21 | block.rect.center = (width // 2, height // 2) # center the text block relatively to the screen 22 | print('*~*~*\npress and hold the space bar ; press ENTER to change alignment') 23 | can_exit = False 24 | 25 | GL_BG_COLOR = (0, 0, 0) 26 | block.debug = 0 27 | 28 | # sert a afficher tous les car. sans exception! 29 | INIT_TXT = "ABCDEFGHIJKLMNOPQRSTUVWXYZa\nabcdefghijklmnopqrstuvwxyz.\n" 30 | INIT_TXT += ".-,:+\'!?0\n0123456789()/_=\\[]*\"<>;@$%{}'\n" 31 | block.text = INIT_TXT 32 | 33 | while not can_exit: 34 | for ev in pygame.event.get(): 35 | if ev.type == pygame.QUIT: 36 | can_exit = True 37 | elif ev.type == pygame.KEYDOWN: 38 | if ev.key == pygame.K_RETURN: 39 | block.text_align = (block.text_align + 1) % 2 # switch text align 40 | elif ev.key == pygame.K_ESCAPE: 41 | can_exit = True 42 | elif ev.type == pygame.KEYUP: 43 | if not pygame.key.get_pressed()[pygame.K_SPACE]: 44 | block.text = INIT_TXT 45 | screen.fill(GL_BG_COLOR) 46 | block.draw(screen) 47 | pyv.flip() 48 | 49 | pyv.quit() 50 | -------------------------------------------------------------------------------- /examples_basic/min-example-gui.py: -------------------------------------------------------------------------------- 1 | import pyved_engine as pyv 2 | pyv.init(2) 3 | 4 | pygame = pyv.pygame 5 | screen = pyv.get_surface() 6 | width, height = screen.get_size() 7 | 8 | INIT_TXT = 'hello user this\nis\nsome\ndope\ntext' 9 | ALT_TXT = 'i\nunderstand that\nyou watch the console' 10 | USING_IMGBASED_FT = True 11 | 12 | if USING_IMGBASED_FT: 13 | ft_obj = pyv.gui.ImgBasedFont( 14 | (15, 130, 243), # we specify: the color that should be viewed as transparent 15 | img=pygame.image.load('mixed_assets/niobe_font.png') 16 | ) # special font format 17 | else: 18 | FT_PATH = 'mixed_assets/alphbeta.ttf' 19 | ft_obj = pygame.font.Font(FT_PATH, 16) 20 | 21 | 22 | block = pyv.gui.TextBlock(ft_obj, INIT_TXT, (0, 0, 0)) 23 | block.rect.center = (width // 2, height // 2) # lets center the text block 24 | print('*~*~*\npress and hold the space bar ; press ENTER to change alignment') 25 | ended = False 26 | 27 | while not ended: 28 | for ev in pygame.event.get(): 29 | if ev.type == pygame.QUIT: 30 | ended = True 31 | elif ev.type == pygame.KEYDOWN: 32 | if ev.key == pygame.K_RETURN: 33 | block.text_align = (block.text_align + 1) % 2 # switch text align 34 | elif ev.key == pygame.K_SPACE: 35 | block.text = ALT_TXT 36 | elif ev.key == pygame.K_ESCAPE: 37 | ended = True 38 | elif ev.type == pygame.KEYUP: 39 | if not pygame.key.get_pressed()[pygame.K_SPACE]: 40 | block.text = INIT_TXT 41 | screen.fill('white') 42 | block.draw(screen) 43 | pyv.flip() 44 | pyv.quit() 45 | -------------------------------------------------------------------------------- /examples_basic/mixed_assets/alphbeta.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples_basic/mixed_assets/alphbeta.ttf -------------------------------------------------------------------------------- /examples_basic/mixed_assets/niobe_font.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/examples_basic/mixed_assets/niobe_font.png -------------------------------------------------------------------------------- /examples_basic/show_pal.py: -------------------------------------------------------------------------------- 1 | import pyved_engine as pyv 2 | import math 3 | 4 | 5 | pyv.bootstrap_e() 6 | 7 | # const 8 | START_POS = (16, 32) 9 | BAR_LENGTH = 300 10 | TILE_HEIGHT = 48 11 | 12 | pygame = pyv.pygame 13 | 14 | 15 | # - init 16 | pyv.init(pyv.LOW_RES_MODE, wcaption='kengi.palettes showcase') 17 | 18 | gameover = False 19 | cl = pygame.time.Clock() 20 | rounding_type = round_func = lambda x: x 21 | ft = pygame.font.Font(None, 25) 22 | 23 | pos2tile = dict() 24 | pos2label = dict() 25 | pos2size = dict() 26 | 27 | curr_offset_y = 0 28 | for name, pal in pyv.pal.ALL_PALETTES.items(): 29 | best_tile_size = (BAR_LENGTH-pal.size+1) / pal.size 30 | t = BAR_LENGTH 31 | curr_offset_x = 0 32 | last_keyy = 0 33 | 34 | for d, col in enumerate(pal.listing): 35 | y = math.ceil(best_tile_size) 36 | tile_size = y if (y < t) else t 37 | t -= tile_size 38 | 39 | last_keyy = keyy = (d + START_POS[0] + curr_offset_x, START_POS[1] + curr_offset_y) 40 | tile_obj = pygame.Surface((tile_size, 8)) 41 | tile_obj.fill(col) 42 | pos2tile[keyy] = tile_obj 43 | 44 | curr_offset_x += tile_size 45 | 46 | pos2label[(last_keyy[0]+24, last_keyy[1]+10)] = ft.render(name, False, (0, 0, 0)) # save a label 47 | pos2size[(last_keyy[0]+30, last_keyy[1] + 22)] = ft.render(f'size #{pal.size}', False, (88, 88, 100)) # another lbl 48 | 49 | curr_offset_y += TILE_HEIGHT 50 | 51 | print('-- util. methods tests --') 52 | 53 | n = 7 54 | print(f'pick any color {n} times (japan pal)') 55 | for _ in range(n): 56 | rcolor = pyv.pal.japan.at_random() 57 | print(rcolor, pyv.pal.japan.get_name(rcolor)) 58 | print() 59 | n = 10 60 | print(f'pick a color {n} times, but no black or white or violet') 61 | for _ in range(n): 62 | rcolor = pyv.pal.c64.at_random(excl_set={'black', 'white', 'violet'}) 63 | print(rcolor, pyv.pal.c64.get_name(rcolor)) 64 | n = 10 65 | print(f'pick a color {n} times, but not 3 or 8 or 9 or 10') 66 | for _ in range(n): 67 | rcolor = pyv.pal.c64.at_random(excl_set={3, 8, 9, 10}) 68 | print(rcolor, pyv.pal.c64.get_rank(rcolor)) 69 | 70 | 71 | # - main program 72 | def run_game(): 73 | global gameover 74 | scr = pyv.get_surface() 75 | 76 | while not gameover: 77 | for ev in pygame.event.get(): 78 | if ev.type == pygame.QUIT: 79 | gameover = True 80 | elif ev.type == pygame.KEYDOWN: 81 | if ev.key == pygame.K_ESCAPE: 82 | gameover = True 83 | # display 84 | scr.fill((0, 0, 255)) 85 | 86 | for p, slabel in pos2size.items(): 87 | scr.blit(slabel, p) 88 | for p, label in pos2label.items(): 89 | scr.blit(label, p) 90 | for p, tile in pos2tile.items(): 91 | scr.blit(tile, p) 92 | 93 | pyv.flip() 94 | cl.tick(60) 95 | 96 | pyv.quit() 97 | print('bye') 98 | 99 | 100 | if __name__ == '__main__': 101 | run_game() 102 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: "PYV game engine: the official docs" 2 | site_url: https://pyved-solution.github.io/pyved-engine/ 3 | repo_url: https://github.com/pyved-solution/pyved-engine 4 | 5 | 6 | nav: 7 | - 'index.md' 8 | - 'Showcase.md' 9 | - 'ActorBasedPattern.md' 10 | - 'Entity Component System': 11 | - 'Entity Component System/A bit of theory.md' 12 | - 'Entity Component System/ECS examples.md' 13 | - 'Other Patterns': 14 | - 'Other patterns/Event based programming.md' 15 | - 'Other patterns/MVC examples.md' 16 | - 'Game Tutorials': 17 | - 'GameTutorials/Breakout.md' 18 | - 'GameTutorials/Platformer.md' 19 | - 'GameTutorials/Roguelike.md' 20 | - 'Reference': 21 | - 'Reference/Using sprites.md' 22 | - 'Reference/Gamestates.md' 23 | - 'ShareYourGames.md' 24 | 25 | 26 | theme: 27 | name: material 28 | font: false 29 | icon: 30 | logo: material/space-invaders 31 | 32 | 33 | extra: 34 | social: 35 | - icon: fontawesome/brands/github 36 | link: https://github.com/pyved-solution/pyved-engine 37 | name: Pyved-engine on Github 38 | 39 | 40 | markdown_extensions: 41 | - admonition 42 | - pymdownx.highlight: 43 | anchor_linenums: true 44 | - pymdownx.superfences 45 | 46 | 47 | plugins: 48 | - search 49 | - i18n: 50 | default_language: !ENV [DEFAULT_LANGUAGE, "en"] 51 | default_language_only: !ENV [DEFAULT_LANGUAGE_ONLY, false] 52 | 53 | languages: 54 | en: 55 | name: English 56 | build: true 57 | fr: 58 | name: Français 59 | build: true 60 | site_name: "Documentation pour PYV: moteur de jeu" 61 | 62 | nav_translations: 63 | fr: 64 | Bidule: bidule.fr 65 | Topic1: Sujet1 66 | Topic2: Sujet2 67 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pygame-ce>=2.2.1 2 | tabulate 3 | pyperclip 4 | requests 5 | attrs 6 | pillow>=11.0.0 7 | setuptools 8 | mkdocs==1.4.3 9 | mkdocs-material==9.1.14 10 | mkdocs-static-i18n==0.56 -------------------------------------------------------------------------------- /runtime-req.txt: -------------------------------------------------------------------------------- 1 | pygame-ce>=2.2.1 2 | tabulate 3 | pyperclip 4 | requests 5 | attrs 6 | pillow>=11.0.0 -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | from pathlib import Path 3 | 4 | lib_folder = os.path.dirname(os.path.realpath(__file__)) 5 | 6 | requirements_file = lib_folder + '/runtime-req.txt' 7 | whats_required = [] # Here we'll get content of requirements.txt 8 | if os.path.isfile(requirements_file): 9 | with open(requirements_file) as fp: 10 | whats_required = fp.read().splitlines() 11 | 12 | # need sys so we can include pyved_engine 13 | import sys 14 | 15 | sys.path.append('src') 16 | from pyved_engine import vars 17 | from setuptools import setup 18 | 19 | pck_list = [ 20 | "pyved_engine", 21 | "pyved_engine.foundation", 22 | "pyved_engine.compo", 23 | "pyved_engine.core", 24 | "pyved_engine.looparts", # to be sure we get looparts/rogue.py, looparts/tabletop.py, etc. 25 | "pyved_engine.looparts.ai", 26 | "pyved_engine.looparts.demolib", 27 | #"pyved_engine.looparts.gui", 28 | 'pyved_engine.add_ons.gui', 29 | 'pyved_engine.add_ons.tmx', 30 | "pyved_engine.add_ons.tmx.pytiled_parser", 31 | "pyved_engine.add_ons.tmx.pytiled_parser.parsers", 32 | "pyved_engine.add_ons.tmx.pytiled_parser.parsers.json", 33 | "pyved_engine.add_ons.tmx.pytiled_parser.parsers.tmx", 34 | 35 | #"pyved_engine.looparts.isometric", 36 | #"pyved_engine.looparts.polarbear", 37 | #"pyved_engine.looparts.tmx", 38 | "pyvcmdline", 39 | "pyvcmdline.pyvcli_cogs", 40 | "pyvcmdline.spare_parts" 41 | ] 42 | 43 | this_directory = Path(__file__).parent 44 | long_desc = (this_directory / "README.md").read_text() 45 | 46 | setup( 47 | name='pyved-engine', 48 | version=str(vars.ENGINE_VERSION_STR), 49 | 50 | description='Custom game engine built upon python/pygame', 51 | long_description=long_desc, 52 | long_description_content_type='text/markdown', 53 | 54 | keywords=['Python', 'Pygame', 'Game Engine'], 55 | author='moonb3ndr et al.', 56 | author_email='thomas.iw@kata.games', 57 | license='LGPL3', 58 | package_dir={'': 'src'}, 59 | packages=pck_list, 60 | url="https://github.com/gaudiatech/pyved-engine", 61 | install_requires=whats_required, 62 | include_package_data=True, 63 | 64 | entry_points={ 65 | 'console_scripts': [ 66 | 'pyv-cli = pyvcmdline.__main__:do_parse_args' 67 | ] 68 | } 69 | ) 70 | -------------------------------------------------------------------------------- /shared.game.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/shared.game.png -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | kengi.egg-info/ 2 | -------------------------------------------------------------------------------- /src/pyvcmdline/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | The following module implements the command line that becomes available, 3 | once the user has installed pyved-engine locally... 4 | 5 | After installation, for example you can type: 6 | "pyv-cli init myGame" 7 | To create a new game bundle. 8 | 9 | There will be many embedded demos: 10 | - chess 11 | - bullethell 12 | - rogue 13 | - ... 14 | """ 15 | -------------------------------------------------------------------------------- /src/pyvcmdline/bundle_ops.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | RUNGAME_SCRIPT_NAME = 'launch_game' # Warning! Use base name (no ext) 4 | -------------------------------------------------------------------------------- /src/pyvcmdline/pyvcli_cogs/__init__.py: -------------------------------------------------------------------------------- 1 | # TODO how to handle this in the future? 2 | 3 | from .autogen_localctx import proc_autogen_localctx 4 | -------------------------------------------------------------------------------- /src/pyvcmdline/pyvcli_defs.py: -------------------------------------------------------------------------------- 1 | """ 2 | this module contains only declarations, tied to the pyv-cli tool implementation. 3 | """ 4 | from pyved_engine import vars as pyv_vars 5 | 6 | 7 | VER_DISP_MSG = 'Pyved-engine %s | github.com/pyved-solution\nAuthors: Thomas I. EDER and others (c) 2018-2024' 8 | 9 | 10 | def read_ver(): 11 | return pyv_vars.ENGINE_VERSION_STR 12 | -------------------------------------------------------------------------------- /src/pyvcmdline/spare_parts/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ce module python va contenir les "spare parts" c-à-d 3 | pièces détachées que la commande pyv-cli utilise pour assembler un 4 | bundle spécifique, à la demande. 5 | 6 | On utilise aussi bien des cartouches de jeu qui servent de template, 7 | que le fichier spécial launch_game.py 8 | décliné en version bundle isolé, ou version bundle réseau... 9 | 10 | Il faut aussi être capable de générer le connecteur py, 11 | lorsqu'on fait de l'assemblage de bundle réseau. 12 | Le script autogen qui s'occupe de ça se base sur API_SPEC.json 13 | """ 14 | -------------------------------------------------------------------------------- /src/pyved_engine/Singleton.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class Singleton: 4 | """ 5 | A non-thread-safe helper class to ease implementing singletons. 6 | This should be used as a decorator -- not a metaclass -- to the 7 | class that should be a singleton. 8 | 9 | The decorated class can define one `__init__` function that 10 | takes only the `self` argument. Also, the decorated class cannot be 11 | inherited from. Other than that, there are no restrictions that apply 12 | to the decorated class. 13 | 14 | To get the singleton instance, use the `instance` method. Trying 15 | to use `__call__` will result in a `TypeError` being raised. 16 | 17 | """ 18 | 19 | def __init__(self, decorated): 20 | self._decorated = decorated 21 | 22 | def instance(self): 23 | """ 24 | Returns the singleton instance. Upon its first call, it creates a 25 | new instance of the decorated class and calls its `__init__` method. 26 | On all subsequent calls, the already created instance is returned. 27 | 28 | """ 29 | try: 30 | return self._instance 31 | except AttributeError: 32 | self._instance = self._decorated() 33 | return self._instance 34 | 35 | def __call__(self): 36 | raise TypeError('Singletons must be accessed through `instance()`.') 37 | 38 | def __instancecheck__(self, inst): 39 | return isinstance(inst, self._decorated) 40 | -------------------------------------------------------------------------------- /src/pyved_engine/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | +----------------------------------------------------+ 3 | | Pyv - a pythonic 2d Game Engine | 4 | | Our motto ~ Never slow down the innovation | 5 | | | 6 | | https://github.com/gaudiatech/pyved-engine | 7 | | an open-source project started by GAUDIA TECH INC. | 8 | | | 9 | | Main author is Thomas EDER a.k.a. moonbak | 10 | | (github.com/wkta) - Contact thomas.iw@kata.games | 11 | +----------------------------------------------------+ 12 | """ 13 | from . import _hub 14 | hub = _hub 15 | 16 | from .context_bridge import * # api is already packed in this file 17 | from . import custom_struct as struct 18 | from .core.events import Emitter, EvListener, EngineEvTypes 19 | from .core import legacy_evs # we just copy the event system of pygame 20 | from ._classes import * 21 | from .Singleton import Singleton 22 | from .compo import gfx 23 | 24 | from . import vars 25 | 26 | # deprecated 27 | from .compo import vscreen 28 | 29 | # TODO remove this when we can 30 | # ive kept it for retro-compatibility with projects that target pyv v23.6a1 31 | # such as demos/ecs_naif or the very early stage pyved ships-with-GUI editor 32 | from ._ecs_pattern import entity, component, System, SystemManager, EntityManager 33 | from . import evsys0 34 | 35 | # useful ALIAS! (webctx) 36 | defs = vars 37 | 38 | 39 | def get_version(): 40 | return vars.ENGINE_VERSION_STR 41 | 42 | 43 | _stored_kbackend = None 44 | # deprec. 45 | vars.weblib_sig = _backend_name = '' 46 | quit = close_game 47 | 48 | 49 | def set_webbackend_type(xval): 50 | global _backend_name 51 | vars.weblib_sig = _backend_name = xval 52 | vars.backend_name = 'web' 53 | 54 | 55 | # the basic API is expanded via our special "hub" component 56 | def __getattr__(attr_name): 57 | if attr_name in ('ver', 'vernum'): 58 | return get_version() 59 | elif attr_name == 'Sprite': 60 | return _hub.pygame.sprite.Sprite 61 | elif attr_name == 'SpriteGroup': 62 | return _hub.pygame.sprite.Group 63 | elif attr_name == 'sprite_collision': 64 | return _hub.pygame.sprite.spritecollide 65 | 66 | return getattr(_hub, attr_name) 67 | -------------------------------------------------------------------------------- /src/pyved_engine/_classes.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta, abstractmethod 2 | from collections import deque 3 | 4 | 5 | __all__ = [ 6 | 'BaseGameState', 7 | 'Objectifier', 8 | 'CircularBuffer' 9 | ] 10 | 11 | 12 | class BaseGameState(metaclass=ABCMeta): 13 | 14 | def __init__(self, state_ident): 15 | self.__state_ident = state_ident 16 | self.__state_name = self.__class__.__name__ 17 | 18 | @abstractmethod 19 | def enter(self): 20 | pass 21 | 22 | def get_id(self): 23 | return self.__state_ident 24 | 25 | def get_name(self): 26 | return self.__state_name 27 | 28 | def pause(self): 29 | print(self.__class__.__name__) 30 | raise AssertionError('not meant to be paused') 31 | 32 | @abstractmethod 33 | def release(self): 34 | pass 35 | 36 | def resume(self): 37 | print(self.__class__.__name__) 38 | raise AssertionError('not meant to be resumed') 39 | 40 | 41 | # may be deprecated, due to pyv.vars 42 | # TODO investigate? 43 | # class ConfigStorage: 44 | # MAXFPS = 45 45 | # SCR_SIZE = (None, None) 46 | # UPSCALING = None # not defined, yet 47 | 48 | 49 | class Objectifier: 50 | def __init__(self, **entries): 51 | self.__dict__.update(entries) 52 | 53 | 54 | class CircularBuffer: 55 | 56 | def __init__(self, gmax_len=128): 57 | """ 58 | Initialize the CircularBuffer with a gmax_len if given. Default size is 128 59 | """ 60 | self.deque_obj = deque(maxlen=gmax_len) 61 | 62 | def __str__(self): 63 | """Return a formatted string representation of this CircularBuffer.""" 64 | items = ['{!r}'.format(item) for item in self.deque_obj] 65 | return '[' + ', '.join(items) + ']' 66 | 67 | def get_size(self): 68 | return len(self.deque_obj) 69 | 70 | def is_empty(self): 71 | """Return True if the head of the CircularBuffer is equal to the tail, 72 | otherwise return False""" 73 | return len(self.deque_obj) == 0 74 | 75 | def is_full(self): 76 | """Return True if the tail of the CircularBuffer is one before the head, 77 | otherwise return False""" 78 | return len(self.deque_obj) == self.deque_obj.maxlen 79 | 80 | def enqueue(self, item): 81 | """Insert an item at the back of the CircularBuffer 82 | Runtime: O(1) Space: O(1)""" 83 | self.deque_obj.append(item) 84 | 85 | def dequeue(self): 86 | """Return the item at the front of the Circular Buffer and remove it 87 | Runtime: O(1) Space: O(1)""" 88 | return self.deque_obj.popleft() 89 | 90 | def front(self): 91 | """Return the item at the front of the CircularBuffer 92 | Runtime: O(1) Space: O(1)""" 93 | if len(self.deque_obj): 94 | return self.deque_obj[len(self.deque_obj) - 1] 95 | raise IndexError('circular buffer is currently empty!') 96 | -------------------------------------------------------------------------------- /src/pyved_engine/add_ons/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/src/pyved_engine/add_ons/__init__.py -------------------------------------------------------------------------------- /src/pyved_engine/add_ons/gui/Button.py: -------------------------------------------------------------------------------- 1 | from ... import _hub 2 | # from ... import event 3 | 4 | 5 | pygame = _hub.pygame 6 | 7 | # event = _hub.events 8 | 9 | # EventReceiver = event.EventReceiver 10 | 11 | 12 | # class ButtonPanel(EventReceiver): 13 | # 14 | # def __init__(self, button_list=None, callbacks=None): 15 | # super().__init__() 16 | # self._lb = list() 17 | # if button_list: 18 | # self._lb.extend(button_list) 19 | # 20 | # if callbacks: 21 | # self._callbacks = callbacks 22 | # else: 23 | # self._callbacks = dict() 24 | # 25 | # def proc_event(self, ev, source): 26 | # if ev.type == pygame.MOUSEBUTTONDOWN: 27 | # for bobj in self._lb: 28 | # if bobj.rect.collidepoint(ev.pos): 29 | # try: 30 | # self._callbacks[bobj.ident]() 31 | # except KeyError: 32 | # self.pev(kataen.EngineEvTypes.BTCLICK, bt_ident=bobj.ident) 33 | 34 | 35 | class Button(pygame.sprite.Sprite): 36 | 37 | free_bt_identifier = 77348 38 | 39 | def __init__(self, pos=None, size=None, label='bt_label', anchor_code=0): 40 | """ 41 | :param pos: 42 | :param size: 43 | :param label: 44 | :param anchor_code: 0: topleft, 1: center 45 | """ 46 | super().__init__() 47 | self.callback = None 48 | 49 | self.ident = Button.free_bt_identifier 50 | Button.free_bt_identifier += 1 51 | 52 | if size: 53 | self._w, self._h = size 54 | else: 55 | self._w, self._h = 128, 40 56 | if pos: 57 | self.pos = list(pos) 58 | self.image = pygame.surface.Surface((self._w, self._h)) 59 | self.image.fill('gray') 60 | 61 | tmp_font = pygame.font.Font(None, 18) 62 | self._lbl = tmp_font.render(label, True, 'navyblue') 63 | self.label = label 64 | offsetx = self._lbl.get_width() // 2 65 | offsety = self._lbl.get_height() // 2 66 | cx, cy = self._w//2, self._h//2 67 | self.image.blit(self._lbl, (cx - offsetx, cy - offsety)) 68 | 69 | pygame.draw.rect(self.image, 'navyblue', (0, 0, self._w-1, self._h-1), 2) 70 | 71 | # adjust position 72 | self.rect = self.image.get_rect() 73 | if not anchor_code: 74 | self.rect.topleft = self.pos 75 | else: 76 | self.rect.center = self.pos 77 | self.anchorcode = anchor_code 78 | 79 | def set_image(self, img): 80 | # KEEP THE ORG. POS! 81 | if not self.anchorcode: 82 | orgx, orgy = self.rect.topleft 83 | else: 84 | orgx, orgy = self.rect.center 85 | 86 | self.image = img 87 | self._w, self._h = img.get_size() 88 | 89 | self.rect = pygame.Rect(0, 0, self._w, self._h) 90 | 91 | # re-generate the position 92 | if not self.anchorcode: 93 | self.rect.topleft = orgx, orgy 94 | else: 95 | self.rect.center = orgx, orgy 96 | 97 | # debug: 98 | # self.image.fill('orange') 99 | pygame.draw.rect(self.image, 'orange', (0, 0, self._w - 1, self._h - 1), 2) 100 | -------------------------------------------------------------------------------- /src/pyved_engine/add_ons/tmx/LICENSE: -------------------------------------------------------------------------------- 1 | pytiled_parser --> version modified by moonb3ndr 2 | the License for this chunk of code is: 3 | 4 | MIT License 5 | 6 | Copyright (c) 2019 Beefy_Swain 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. -------------------------------------------------------------------------------- /src/pyved_engine/add_ons/tmx/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | TMX loading capabilities... 3 | 4 | joint work: 5 | - Richard Jones , 6 | - Renfred Harper 7 | - wkta-tom 8 | """ 9 | 10 | from . import misc 11 | from . import data 12 | from . import pytiled_parser 13 | 14 | 15 | _cached_ztm = None 16 | 17 | def get_ztilemap_module(): 18 | global _cached_ztm 19 | if not _cached_ztm: 20 | from . import ztilemap as _extra_module 21 | _cached_ztm = _extra_module 22 | return _cached_ztm 23 | -------------------------------------------------------------------------------- /src/pyved_engine/add_ons/tmx/pytiled_parser/__init__.py: -------------------------------------------------------------------------------- 1 | """Parse Tiled Maps and Tilesets 2 | 3 | See: https://www.mapeditor.org/ 4 | 5 | This library is for parsing JSON formatted Tiled Map Editormaps and tilesets to be 6 | used as maps and levels for 2D top-down (orthogonal, hexogonal, or isometric) 7 | or side-scrolling games in a strictly typed fashion. 8 | 9 | PyTiled Parser is not tied to any particular graphics library or game engine. 10 | """ 11 | 12 | # pylint: disable=too-few-public-methods 13 | 14 | from .common_types import Color, OrderedPair, Size 15 | from .exception import UnknownFormat 16 | from .layer import Chunk, ImageLayer, Layer, LayerGroup, ObjectLayer, TileLayer 17 | from .parser import parse_map, parse_world 18 | from .properties import Properties, Property 19 | from .tiled_map import TiledMap 20 | from .tileset import Frame, Grid, Tile, Tileset, Transformations 21 | from .version import __version__ 22 | from .world import World, WorldMap 23 | -------------------------------------------------------------------------------- /src/pyved_engine/add_ons/tmx/pytiled_parser/common_types.py: -------------------------------------------------------------------------------- 1 | """Module containing types that are common to other modules.""" 2 | 3 | # pylint: disable=too-few-public-methods 4 | 5 | from typing import NamedTuple 6 | 7 | 8 | class Color(NamedTuple): 9 | """Represents an RGBA color value as a four value Tuple. 10 | 11 | Attributes: 12 | red: Red value, between 0 and 255. 13 | green: Green value, between 0 and 255. 14 | blue: Blue value, between 0 and 255. 15 | alpha: Alpha value, between 0 and 255. 16 | """ 17 | 18 | red: int 19 | green: int 20 | blue: int 21 | alpha: int 22 | 23 | 24 | class Size(NamedTuple): 25 | """Represents a two dimensional size as a two value Tuple. 26 | 27 | Attributes: 28 | width: The width of the object. Can be in either pixels or number of tiles. 29 | height: The height of the object. Can be in either pixels or number of tiles. 30 | """ 31 | 32 | width: float 33 | height: float 34 | 35 | 36 | class OrderedPair(NamedTuple): 37 | """Represents a two dimensional position as a two value Tuple. 38 | 39 | Attributes: 40 | x: X coordinate. Can be in either pixels or number of tiles. 41 | y: Y coordinate. Can be in either pixels or number of tiles. 42 | """ 43 | 44 | x: float 45 | y: float 46 | -------------------------------------------------------------------------------- /src/pyved_engine/add_ons/tmx/pytiled_parser/exception.py: -------------------------------------------------------------------------------- 1 | class UnknownFormat(Exception): 2 | pass 3 | -------------------------------------------------------------------------------- /src/pyved_engine/add_ons/tmx/pytiled_parser/parser.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | 3 | from . import UnknownFormat 4 | from .parsers.json.tiled_map import parse as json_map_parse 5 | from .parsers.tmx.tiled_map import parse as tmx_map_parse 6 | from .tiled_map import TiledMap 7 | from .util import check_format 8 | from .world import World 9 | from .world import parse_world as _parse_world 10 | 11 | 12 | def parse_map(file: Path) -> TiledMap: 13 | """Parse the raw Tiled map into a pytiled_parser type 14 | 15 | Args: 16 | file: Path to the map file 17 | 18 | Returns: 19 | TiledMap: A parsed and typed TiledMap 20 | """ 21 | parser = check_format(file) 22 | 23 | # The type ignores are because mypy for some reason thinks those functions return Any 24 | if parser == "tmx": 25 | return tmx_map_parse(file) # type: ignore 26 | else: 27 | try: 28 | return json_map_parse(file) # type: ignore 29 | except ValueError: 30 | raise UnknownFormat( 31 | "Unknown Map Format, please use either the TMX or JSON format. " 32 | "This message could also mean your map file is invalid or corrupted." 33 | ) 34 | 35 | 36 | def parse_world(file: Path) -> World: 37 | """Parse the raw world file into a pytiled_parser type 38 | 39 | Args: 40 | file: Path to the world file 41 | 42 | Returns: 43 | World: A parsed and typed World 44 | """ 45 | return _parse_world(file) 46 | -------------------------------------------------------------------------------- /src/pyved_engine/add_ons/tmx/pytiled_parser/parsers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/src/pyved_engine/add_ons/tmx/pytiled_parser/parsers/__init__.py -------------------------------------------------------------------------------- /src/pyved_engine/add_ons/tmx/pytiled_parser/parsers/json/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/src/pyved_engine/add_ons/tmx/pytiled_parser/parsers/json/__init__.py -------------------------------------------------------------------------------- /src/pyved_engine/add_ons/tmx/pytiled_parser/parsers/json/properties.py: -------------------------------------------------------------------------------- 1 | """Property parsing for the JSON Map Format 2 | """ 3 | 4 | from pathlib import Path 5 | from typing import List, Union, cast 6 | # from typing_extensions import TypedDict 7 | from ...properties import Properties, Property 8 | from ...util import parse_color 9 | 10 | 11 | # RawValue = Union[float, str, bool] 12 | 13 | RawValue = float 14 | 15 | # class RawProperty(TypedDict): 16 | # """The keys and their values that appear in a Tiled JSON Property Object. 17 | # 18 | # Tiled Docs: https://doc.mapeditor.org/en/stable/reference/json-map-format/#property 19 | # """ 20 | # name: str 21 | # type: str 22 | # value: RawValue 23 | 24 | 25 | def parse(raw_properties): #: List[RawProperty]) -> Properties: 26 | """Parse a list of `RawProperty` objects into `Properties`. 27 | 28 | Args: 29 | raw_properties: The list of `RawProperty` objects to parse. 30 | 31 | Returns: 32 | Properties: The parsed `Property` objects. 33 | """ 34 | 35 | final: Properties = {} 36 | value: Property 37 | 38 | for raw_property in raw_properties: 39 | if raw_property["type"] == "file": 40 | value = Path(cast(str, raw_property["value"])) 41 | elif raw_property["type"] == "color": 42 | value = parse_color(cast(str, raw_property["value"])) 43 | else: 44 | value = raw_property["value"] 45 | final[raw_property["name"]] = value 46 | 47 | return final 48 | -------------------------------------------------------------------------------- /src/pyved_engine/add_ons/tmx/pytiled_parser/parsers/tmx/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/src/pyved_engine/add_ons/tmx/pytiled_parser/parsers/tmx/__init__.py -------------------------------------------------------------------------------- /src/pyved_engine/add_ons/tmx/pytiled_parser/parsers/tmx/properties.py: -------------------------------------------------------------------------------- 1 | import xml.etree.ElementTree as etree 2 | from pathlib import Path 3 | from ...properties import Properties, Property 4 | from ...util import parse_color 5 | 6 | 7 | def parse(raw_properties: etree.Element) -> Properties: 8 | 9 | final: Properties = {} 10 | value: Property 11 | 12 | for raw_property in raw_properties.findall("property"): 13 | 14 | type_ = raw_property.attrib.get("type") 15 | 16 | if "value" not in raw_property.attrib: 17 | continue 18 | 19 | value_ = raw_property.attrib["value"] 20 | 21 | if type_ == "file": 22 | value = Path(value_) 23 | elif type_ == "color": 24 | value = parse_color(value_) 25 | elif type_ == "int" or type_ == "float": 26 | value = float(value_) 27 | elif type_ == "bool": 28 | if value_ == "true": 29 | value = True 30 | else: 31 | value = False 32 | else: 33 | value = value_ 34 | final[raw_property.attrib["name"]] = value 35 | 36 | return final 37 | -------------------------------------------------------------------------------- /src/pyved_engine/add_ons/tmx/pytiled_parser/parsers/tmx/wang_set.py: -------------------------------------------------------------------------------- 1 | import xml.etree.ElementTree as etree 2 | from ...parsers.tmx.properties import parse as parse_properties 3 | from ...util import parse_color 4 | # from ...wang_set import WangColor, WangSet, WangTile 5 | 6 | 7 | def _parse_wang_tile(raw_wang_tile: etree.Element): # -> WangTile: 8 | """Parse the raw wang tile into a pytiled_parser type 9 | 10 | Args: 11 | raw_wang_tile: XML Element to be parsed. 12 | 13 | Returns: 14 | WangTile: A properly typed WangTile. 15 | """ 16 | ids = [int(v.strip()) for v in raw_wang_tile.attrib["wangid"].split(",")] 17 | return WangTile(tile_id=int(raw_wang_tile.attrib["tileid"]), wang_id=ids) 18 | 19 | 20 | def _parse_wang_color(raw_wang_color: etree.Element): # -> WangColor: 21 | """Parse the raw wang color into a pytiled_parser type 22 | 23 | Args: 24 | raw_wang_color: XML Element to be parsed. 25 | 26 | Returns: 27 | WangColor: A properly typed WangColor. 28 | """ 29 | wang_color = WangColor( 30 | name=raw_wang_color.attrib["name"], 31 | color=parse_color(raw_wang_color.attrib["color"]), 32 | tile=int(raw_wang_color.attrib["tile"]), 33 | probability=float(raw_wang_color.attrib["probability"]), 34 | ) 35 | 36 | if raw_wang_color.attrib.get("class") is not None: 37 | wang_color.class_ = raw_wang_color.attrib["class"] 38 | 39 | properties = raw_wang_color.find("./properties") 40 | if properties: 41 | wang_color.properties = parse_properties(properties) 42 | 43 | return wang_color 44 | 45 | 46 | def parse(raw_wangset: etree.Element): # -> WangSet: 47 | """Parse the raw wangset into a pytiled_parser type 48 | 49 | Args: 50 | raw_wangset: XML Element to be parsed. 51 | 52 | Returns: 53 | WangSet: A properly typed WangSet. 54 | """ 55 | 56 | colors = [] 57 | for raw_wang_color in raw_wangset.findall("./wangcolor"): 58 | colors.append(_parse_wang_color(raw_wang_color)) 59 | 60 | tiles = {} 61 | for raw_wang_tile in raw_wangset.findall("./wangtile"): 62 | tiles[int(raw_wang_tile.attrib["tileid"])] = _parse_wang_tile(raw_wang_tile) 63 | 64 | wangset = WangSet( 65 | name=raw_wangset.attrib["name"], 66 | tile=int(raw_wangset.attrib["tile"]), 67 | wang_type=raw_wangset.attrib["type"], 68 | wang_colors=colors, 69 | wang_tiles=tiles, 70 | ) 71 | 72 | if raw_wangset.attrib.get("class") is not None: 73 | wangset.class_ = raw_wangset.attrib["class"] 74 | 75 | properties = raw_wangset.find("./properties") 76 | if properties: 77 | wangset.properties = parse_properties(properties) 78 | 79 | return wangset 80 | -------------------------------------------------------------------------------- /src/pyved_engine/add_ons/tmx/pytiled_parser/properties.py: -------------------------------------------------------------------------------- 1 | """Properties Module 2 | 3 | This module defines types for Property objects. 4 | For more about properties in Tiled maps see the below link: 5 | https://doc.mapeditor.org/en/stable/manual/custom-properties/ 6 | 7 | The types defined in this module get added to other objects 8 | such as Layers, Maps, Objects, etc 9 | """ 10 | 11 | from pathlib import Path 12 | from typing import Dict, Union 13 | 14 | from .common_types import Color 15 | 16 | Property = Union[float, Path, str, bool, Color] 17 | 18 | Properties = Dict[str, Property] 19 | -------------------------------------------------------------------------------- /src/pyved_engine/add_ons/tmx/pytiled_parser/util.py: -------------------------------------------------------------------------------- 1 | """Utility Functions for PyTiled""" 2 | import json 3 | import xml.etree.ElementTree as etree 4 | from pathlib import Path 5 | from typing import Any 6 | from .common_types import Color 7 | 8 | 9 | def parse_color(color: str) -> Color: 10 | """Convert Tiled color format into PyTiled's. 11 | 12 | Tiled's color format is #AARRGGBB and PyTiled's is an RGBA tuple. 13 | 14 | Args: 15 | color (str): Tiled formatted color string. 16 | Returns: 17 | :Color: Color object in the format that PyTiled understands. 18 | """ 19 | # the actual part we care about is always an even number 20 | if len(color) % 2: 21 | # strip initial '#' character 22 | color = color[1:] 23 | 24 | if len(color) == 6: 25 | # full opacity if no alpha specified 26 | return Color(int(color[0:2], 16), int(color[2:4], 16), int(color[4:6], 16), 255) 27 | elif len(color) == 8: 28 | return Color( 29 | int(color[2:4], 16), 30 | int(color[4:6], 16), 31 | int(color[6:8], 16), 32 | int(color[0:2], 16), 33 | ) 34 | 35 | raise ValueError("Improperly formatted color passed to parse_color") 36 | 37 | 38 | def check_format(file_path) -> str: # file_path: Path 39 | with open(file_path) as file: 40 | line = file.readline().rstrip().strip() 41 | if line[0] == "<": 42 | return "tmx" 43 | else: 44 | return "json" 45 | 46 | 47 | def load_object_template(file_path: Path) -> Any: 48 | template_format = check_format(file_path) 49 | 50 | new_tileset = None 51 | new_tileset_path = None 52 | 53 | if template_format == "tmx": 54 | with open(file_path) as template_file: 55 | template = etree.parse(template_file).getroot() 56 | 57 | tileset_element = template.find("./tileset") 58 | if tileset_element is not None: 59 | tileset_path = Path(file_path.parent / tileset_element.attrib["source"]) 60 | new_tileset = load_object_tileset(tileset_path) 61 | new_tileset_path = tileset_path.parent 62 | else: 63 | with open(file_path) as template_file: 64 | template = json.load(template_file) 65 | if "tileset" in template: 66 | tileset_path = Path(file_path.parent / template["tileset"]["source"]) # type: ignore 67 | new_tileset = load_object_tileset(tileset_path) 68 | new_tileset_path = tileset_path.parent 69 | 70 | return (template, new_tileset, new_tileset_path) 71 | 72 | 73 | def load_object_tileset(file_path: Path) -> Any: 74 | tileset_format = check_format(file_path) 75 | 76 | new_tileset = None 77 | 78 | with open(file_path) as tileset_file: 79 | if tileset_format == "tmx": 80 | new_tileset = etree.parse(tileset_file).getroot() 81 | else: 82 | new_tileset = json.load(tileset_file) 83 | 84 | return new_tileset 85 | -------------------------------------------------------------------------------- /src/pyved_engine/add_ons/tmx/pytiled_parser/version.py: -------------------------------------------------------------------------------- 1 | """pytiled_parser version""" 2 | 3 | __version__ = "2.2.0" 4 | -------------------------------------------------------------------------------- /src/pyved_engine/add_ons/tmx/pytiled_parser/wang_set.py: -------------------------------------------------------------------------------- 1 | """This module contains a number of classes related to Wang Sets. 2 | 3 | Wang Sets are the underlying data used by Tiled's terrain system. 4 | See [Tiled's docs about terrain](https://doc.mapeditor.org/en/stable/manual/terrain/) 5 | and also the [TMX Reference](https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#wangsets) 6 | and the [JSON Reference](https://doc.mapeditor.org/en/stable/reference/json-map-format/#wang-set) 7 | """ 8 | from typing import Dict, List, Optional 9 | 10 | import attr 11 | 12 | from ..common_types import Color 13 | from pytiled_parser.properties import Properties 14 | 15 | 16 | @attr.s(auto_attribs=True) 17 | class WangTile: 18 | """Defines a Wang tile by linking a tile in the tileset to a Wang ID. 19 | 20 | [TMX Reference](https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#wangtile) 21 | 22 | [JSON Reference](https://doc.mapeditor.org/en/stable/reference/json-map-format/#wang-tile) 23 | 24 | Attributes: 25 | tile_id: The ID of the tile this WangTile maps to 26 | wang_id: The wang color indexes for this tile. This is a list of IDs referring 27 | to colors within the wang set. In the order of top, top right, right, 28 | bottom right, bottom, bottom left, left, top left. 29 | """ 30 | 31 | tile_id: int 32 | wang_id: List[int] 33 | 34 | 35 | @attr.s(auto_attribs=True) 36 | class WangColor: 37 | """A color that can be used to define the corner and/or edge of a Wang tile 38 | 39 | [TMX Reference](https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#wangcolor) 40 | 41 | [JSON Reference](https://doc.mapeditor.org/en/stable/reference/json-map-format/#wang-color) 42 | 43 | Attributes: 44 | color: An RGBA color used to identify this Wang color 45 | name: The name for this color 46 | probability: The probability used when randomizing tiles 47 | properties: The properties for this wang color 48 | class_: The Tiled class of this Wang Color 49 | tile: Tile ID of the tile representing this color 50 | """ 51 | 52 | color: Color 53 | name: str 54 | probability: float 55 | tile: int 56 | class_: Optional[str] = None 57 | properties: Optional[Properties] = None 58 | 59 | 60 | @attr.s(auto_attribs=True) 61 | class WangSet: 62 | """A complete Wang Set defining a list of corner and edge 63 | [WangColors][pytiled_parser.wang_set.WangColor], and any number of 64 | [WangTiles][pytiled_parser.wang_set.WangTile] 65 | 66 | [TMX Reference](https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#wangset) 67 | 68 | [JSON Reference](https://doc.mapeditor.org/en/stable/reference/json-map-format/#wang-set) 69 | 70 | Attributes: 71 | name: Name of the WangSet 72 | properties: The properties for this wang set 73 | class_: The Tiled class of this Wang Set 74 | tile: Tile ID of the tile representing this Wang Set 75 | wang_colors: A list of [WangColors][pytiled_parser.wang_set.WangColor] 76 | wang_tiles: A list of [WangTiles][pytiled_parser.wang_set.WangTile] 77 | wang_type: A string noting the type of this wang set 78 | """ 79 | 80 | name: str 81 | tile: int 82 | wang_type: str 83 | wang_tiles: Dict[int, WangTile] 84 | wang_colors: List[WangColor] 85 | class_: Optional[str] = None 86 | properties: Optional[Properties] = None 87 | -------------------------------------------------------------------------------- /src/pyved_engine/caps/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/src/pyved_engine/caps/__init__.py -------------------------------------------------------------------------------- /src/pyved_engine/caps/bioslike/KataFrameC.py: -------------------------------------------------------------------------------- 1 | import katagames_sdk.api as katapi 2 | import katagames_sdk.capsule.engine_ground.conf_eng as cgmconf 3 | from katagames_sdk.capsule.pygame_provider import get_module 4 | from katagames_sdk.engine import EventReceiver, EngineEvTypes 5 | 6 | 7 | pygame = get_module() 8 | 9 | 10 | class KataFrameC(EventReceiver): 11 | 12 | def __init__(self, ref_mod, ref_view): 13 | super().__init__() 14 | self.ref_mod = ref_mod 15 | self.ref_view = ref_view 16 | self.glvars_module = None 17 | 18 | def proc_event(self, ev, source): 19 | 20 | if ev.type == EngineEvTypes.DOAUTH: 21 | self._handle_auth() 22 | 23 | elif ev.type == pygame.KEYDOWN: 24 | self._handle_keypress(ev) 25 | 26 | elif ev.type == pygame.QUIT: 27 | self.pev(EngineEvTypes.POPSTATE) 28 | 29 | def _handle_auth(self): 30 | login_feedback = katapi.try_auth_server(self.ref_mod.username, self.ref_mod.plainpwd) 31 | 32 | if login_feedback: 33 | username, acc_id = self.ref_mod.username, int(login_feedback) 34 | self.glvars_module.username = username 35 | self.glvars_module.acc_id = acc_id 36 | 37 | if cgmconf.runs_in_web(): 38 | print('commit to session_storage ->ye') 39 | katapi.save_to_local_session(username, acc_id) 40 | self.pev(EngineEvTypes.CHANGESTATE, state_ident=0) 41 | 42 | else: 43 | self.ref_mod.reset_fields() 44 | # gestion refus -> affiche un message erreur 45 | self.ref_view.sig_bad_auth() 46 | 47 | def _handle_keypress(self, ev): 48 | if ev.key == pygame.K_RETURN or ev.key == pygame.K_KP_ENTER: 49 | pass 50 | 51 | elif ev.key == pygame.K_ESCAPE: 52 | self.pev(EngineEvTypes.POPSTATE) 53 | 54 | elif ev.key == pygame.K_TAB: 55 | return # sert à ignorer caractères TAB ds la saisie 56 | 57 | elif ev.key == pygame.K_BACKSPACE: 58 | self.ref_mod.suppr_lettre() 59 | 60 | else: 61 | self.ref_mod.input_char(ev.unicode) # register the key 62 | -------------------------------------------------------------------------------- /src/pyved_engine/caps/bioslike/KataFrameM.py: -------------------------------------------------------------------------------- 1 | from katagames_sdk.capsule.event import CogObject 2 | from katagames_sdk.capsule.event import EngineEvTypes 3 | 4 | 5 | class KataFrameM(CogObject): 6 | """ 7 | classe utilisée pr stocker temporairement login / pwd 8 | durant le processus de login 9 | Le pwd est gardé secret (pas d'affichage) mais on compte et 10 | on affiche correctement le nb de car 11 | """ 12 | VAR_USERNAME, VAR_PWD = range(87, 87 + 2) 13 | 14 | def __init__(self): 15 | super().__init__() 16 | self._username_info = '' 17 | self._pwdplain_info = '' 18 | 19 | self._focusing_username = True 20 | 21 | def input_char(self, c): 22 | if self._focusing_username: 23 | self._username_info += c 24 | else: 25 | self._pwdplain_info += c 26 | 27 | # - getters 28 | @property 29 | def username(self): 30 | return self._username_info 31 | 32 | @property 33 | def plainpwd(self): 34 | return self._pwdplain_info 35 | 36 | def get_pwd_str(self): 37 | k = len(self._pwdplain_info) 38 | li_etoiles = '*' * k 39 | return ''.join(li_etoiles) 40 | 41 | def is_focusing_username(self): 42 | return self._focusing_username 43 | 44 | # - misc methods 45 | def set_focus(self, var_code): 46 | 47 | if var_code == self.VAR_USERNAME: 48 | if not self._focusing_username: 49 | self._focusing_username = True 50 | self.pev(EngineEvTypes.FOCUSCH, focusing_username=True) 51 | 52 | elif var_code == self.VAR_PWD: 53 | if self._focusing_username: 54 | self._focusing_username = False 55 | self.pev(EngineEvTypes.FOCUSCH, focusing_username=False) 56 | else: 57 | raise ValueError('unrecognized var_code') 58 | 59 | def toggle_focus(self): 60 | self._focusing_username = not self._focusing_username 61 | self.pev(EngineEvTypes.FOCUSCH, focusing_username=self._focusing_username) 62 | 63 | def suppr_lettre(self): 64 | if self._focusing_username: 65 | if len(self._username_info) > 0: 66 | self._username_info = self._username_info[:-1] 67 | self.pev(EngineEvTypes.FIELDCH, field=0, txt=self._username_info) 68 | else: 69 | if len(self._pwdplain_info) > 0: 70 | self._pwdplain_info = self._pwdplain_info[:-1] 71 | self.pev(EngineEvTypes.FIELDCH, field=1, txt=self.get_pwd_str()) 72 | 73 | def reset_fields(self): 74 | self._username_info = '' 75 | self._pwdplain_info = '' 76 | 77 | self.pev(EngineEvTypes.FIELDCH, field=0, txt=self._username_info) 78 | self.pev(EngineEvTypes.FIELDCH, field=1, txt=self.get_pwd_str()) 79 | 80 | self._focusing_username = True 81 | self.pev(EngineEvTypes.FOCUSCH, focusing_username=True) 82 | -------------------------------------------------------------------------------- /src/pyved_engine/caps/bioslike/MicroView.py: -------------------------------------------------------------------------------- 1 | import katagames_sdk.capsule.engine_ground.conf_eng as cgmconf 2 | from katagames_sdk.capsule.event import EventReceiver, EngineEvTypes 3 | from katagames_sdk.capsule.pygame_provider import get_module 4 | 5 | pyg = get_module() 6 | 7 | 8 | class MicroView(EventReceiver): 9 | def __init__(self): 10 | super().__init__() 11 | fgcolor, self.bgcolor = pyg.color.Color('purple'), pyg.color.Color('antiquewhite3') 12 | 13 | self._font = pyg.font.Font(None, 22) 14 | 15 | self._label = self._font.render('CLICK HERE TO PLAY!', False, fgcolor) 16 | scr_w, scr_h = cgmconf.get_screen().get_size() 17 | self._pos = ( 18 | (scr_w - self._label.get_width())//2, 19 | (scr_h - self._label.get_height())//2 20 | ) 21 | 22 | def proc_event(self, ev, source): 23 | if ev.type == EngineEvTypes.PAINT: 24 | ev.screen.fill(self.bgcolor) 25 | ev.screen.blit(self._label, self._pos) 26 | 27 | elif ev.type == pyg.MOUSEBUTTONUP: 28 | self.pev(EngineEvTypes.CHANGESTATE, state_ident=0) 29 | -------------------------------------------------------------------------------- /src/pyved_engine/caps/bioslike/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/src/pyved_engine/caps/bioslike/__init__.py -------------------------------------------------------------------------------- /src/pyved_engine/caps/engine_ground/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/src/pyved_engine/caps/engine_ground/__init__.py -------------------------------------------------------------------------------- /src/pyved_engine/caps/engine_ground/util.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | 4 | def underscore_format(name): 5 | s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name) 6 | return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower() 7 | 8 | 9 | def camel_case_format(string_ac_underscores): 10 | words = [word.capitalize() for word in string_ac_underscores.split('_')] 11 | return "".join(words) 12 | -------------------------------------------------------------------------------- /src/pyved_engine/caps/networking/EnvoiAsynchrone2.py: -------------------------------------------------------------------------------- 1 | import threading 2 | 3 | # import urllib.parse as pp 4 | #  from http.client import HTTPConnection 5 | from katagames_sdk.capsule.networking.httpserver import HttpServer 6 | 7 | 8 | class EnvoiAsynchrone2(threading.Thread): 9 | NB_INST_MAX = 16 10 | 11 | nb_courant_instances = 0 12 | 13 | PORT = None 14 | HOST_STR = None 15 | 16 | def __init__(self, id_req, http_ressource, opt_data, test_timestamp=None): 17 | cls = self.__class__ 18 | 19 | if cls.nb_courant_instances >= cls.NB_INST_MAX: 20 | raise Exception('Nb. maximum d\' appels asynchrones atteint') 21 | 22 | self.id_req = id_req # utile pour fournir reponse via CgmEvent !! 23 | 24 | # self.test_timestamp = '1523728737' if (test_timestamp is None) else test_timestamp 25 | 26 | threading.Thread.__init__(self) 27 | cls.nb_courant_instances += 1 28 | 29 | self.post_data = opt_data # peut être None si on fait du get, ou set correctement pour du POST 30 | 31 | # - TEMPORAIRE 32 | # self.server_port = self.__class__.PORT 33 | # self.host = self.__class__.HOST_STR 34 | 35 | # pr long-polling 36 | # self.url_pr_server_time = None 37 | 38 | self.target_http_ressource = http_ressource 39 | self.zombie_thread = threading.Event() 40 | self.response = None 41 | 42 | # self.cb = None 43 | 44 | # def setup_callback(self, cb): 45 | # self.cb = cb 46 | 47 | def __del__(self): 48 | self.__class__.nb_courant_instances -= 1 49 | 50 | # était utilisé pour le long polling... 51 | # def stop(self): 52 | # pass 53 | # self.cli_http.close() 54 | 55 | # def f_long_polling_packet(self, ts_arg): 56 | # if self.server_port is None: # si non initialisé 57 | # self.server_port = 80 58 | # self.host = '192.168.1.99' 59 | # self.url_pr_server_time = '/tom/server.php' 60 | # self.debug_mode = True 61 | # 62 | # #self.cli_http = HTTPConnection(self.host) 63 | # #self.cli_http.connect() 64 | # 65 | # # transmission 66 | # msg = self.url_pr_server_time + '?timestamp={}'.format(ts_arg) 67 | # 68 | # res = EnvoiAsynchrone2._commit_to_netw(self.host, msg) 69 | # return res 70 | 71 | def run(self): 72 | url = 'http://{}:{}/{}'.format(EnvoiAsynchrone2.HOST_STR, EnvoiAsynchrone2.PORT, self.target_http_ressource) 73 | 74 | if self.post_data is not None: 75 | self.response = HttpServer.instance().proxied_post(url, {'data': self.post_data}) 76 | else: 77 | self.response = HttpServer.instance().proxied_get(url, {}) 78 | 79 | self.zombie_thread.set() # indique que la tâche du thread est terminée 80 | -------------------------------------------------------------------------------- /src/pyved_engine/caps/networking/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/src/pyved_engine/caps/networking/__init__.py -------------------------------------------------------------------------------- /src/pyved_engine/caps/struct/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/src/pyved_engine/caps/struct/__init__.py -------------------------------------------------------------------------------- /src/pyved_engine/caps/struct/matricks.py: -------------------------------------------------------------------------------- 1 | import abc 2 | 3 | 4 | # --- trick from stackoverflow... 5 | class abstractclassmethod(classmethod): 6 | __isabstractmethod__ = True 7 | 8 | def __init__(self, fcallable): 9 | callable.__isabstractmethod__ = True 10 | super(abstractclassmethod, self).__init__(fcallable) 11 | 12 | 13 | class BaseMatrix(object): 14 | """ 15 | classe ABSTRAITE 16 | représentation 1d dune matrice bidimensionnelle de taille connue 17 | """ 18 | __metaclass__ = abc.ABCMeta 19 | 20 | def __init__(self, matr_size, li1d_val_init=None): 21 | self.width, self.height = matr_size 22 | nb_elem = self.width * self.height 23 | if li1d_val_init is not None: 24 | if len(li1d_val_init) != nb_elem: 25 | raise ValueError('val pour init matrice incoherentes') 26 | for elt in li1d_val_init: 27 | if not self.__class__.is_valid_val(elt): 28 | raise ValueError('val type doesnt match matrix type, elt={}'.format(elt)) 29 | self.repr_1d = li1d_val_init 30 | else: 31 | self.repr_1d = [self.__class__.default_val()] * nb_elem 32 | 33 | @abstractclassmethod 34 | def default_val(cls): 35 | pass 36 | 37 | @abstractclassmethod 38 | def is_valid_val(cls, val): 39 | pass 40 | 41 | def get_val(self, i, j): 42 | if self.is_out(i, j): 43 | raise ValueError('coords {} {} out of bounds for the current matrix'.format(i, j)) 44 | adhoc_ind = j * self.width + i 45 | return self.repr_1d[adhoc_ind] 46 | 47 | def set_val(self, i, j, val): 48 | if not self.__class__.is_valid_val(val): 49 | raise ValueError( 50 | 'val {} incompatible avec le type de matrice utilisé ({})'.format(val, self.__class__.__name__) 51 | ) 52 | ind = j * self.width + i 53 | self.repr_1d[ind] = val 54 | 55 | def set_all_values(self, val): 56 | for i in range(self.width): 57 | for j in range(self.height): 58 | self.set_val(i, j, val) 59 | 60 | def is_out(self, i, j): 61 | return not (0 <= i < self.width and 0 <= j < self.height) 62 | 63 | def get_size(self): 64 | return self.width, self.height 65 | 66 | def __str__(self): 67 | res = '{} x {} matrix'.format(self.width, self.height) 68 | res += "\n" 69 | for j in range(self.height): 70 | for i in range(self.width): 71 | ind = j * self.width + i 72 | res += ' {}'.format(self.repr_1d[ind]) 73 | res += "\n" 74 | return res 75 | 76 | 77 | class IntegerMatrix(BaseMatrix): 78 | """ 79 | modélise une matrice d'entiers. Par défaut, toutes les cellules sont à 0 80 | """ 81 | 82 | # --- redefinition de 2 methodes venant den haut 83 | @classmethod 84 | def default_val(cls): 85 | return None # TODO faire en sorte que ce soit 0 mais faudra modifer RandomMaze avant cela 86 | 87 | @classmethod 88 | def is_valid_value(cls, val): 89 | return (val is None) or isinstance(val, int) 90 | -------------------------------------------------------------------------------- /src/pyved_engine/compo/GameTpl.py: -------------------------------------------------------------------------------- 1 | import time 2 | from abc import ABCMeta, abstractmethod 3 | from .. import _hub 4 | from .. import context_bridge as gamedev_api 5 | from ..core.events import EvManager, EngineEvTypes 6 | from .. import vars as engine_vars 7 | 8 | 9 | class GameTpl(metaclass=ABCMeta): 10 | """ 11 | the "no name" game template class. It allows to define your game in a quick way, 12 | by redefining one or several methods: enter, update, exit 13 | """ 14 | INFO_STOP_MSG = 'kengi.GameTpl->the loop() call has ended.' 15 | ERR_LOCK_MSG = 'kengi.GameTpl.loop called while SAFETY_LOCK is on!' 16 | SAFETY_LOCK = False # can be set to True from outside, if you don't want a game to call .loop() 17 | 18 | def __init__(self): 19 | self.gameover = False 20 | self.nxt_game = 'niobepolis' 21 | self._manager = None 22 | 23 | @abstractmethod 24 | def get_video_mode(self): 25 | raise NotImplementedError 26 | 27 | @abstractmethod 28 | def list_game_events(self): 29 | """ 30 | :return: all specific/custom game events. If nothing applies you can return None or [] 31 | """ 32 | raise NotImplementedError 33 | 34 | def list_game_states(self): 35 | """ 36 | :return: all specific states(scenes) of the game! 37 | None, None should be returned as a signal that game doesnt need to use the state manager! 38 | """ 39 | return None, None 40 | 41 | def enter(self, vms=None): 42 | """ 43 | Careful if you redefine this: 44 | one *HAS TO* 45 | - init video 46 | - set the gameticker 47 | - set the _manager attribute (bind the ev manager to self._manager) 48 | - call self._manager.setup(...) with args 49 | """ 50 | gamedev_api.init(mode=self.get_video_mode()) 51 | self._manager = EvManager.instance() 52 | self._manager.setup(self.list_game_events()) 53 | self._manager.post(EngineEvTypes.Gamestart) # pushed to notify that we have really started playing 54 | gs_enum, mapping = self.list_game_states() 55 | if gs_enum is not None: 56 | gamedev_api.declare_game_states(gs_enum, mapping, self) 57 | 58 | def update(self, infot): 59 | pyg = _hub.pygame 60 | pk = pyg.key.get_pressed() 61 | if pk[pyg.K_ESCAPE]: 62 | self.gameover = True 63 | return 2, self.nxt_game 64 | 65 | self._manager.post(EngineEvTypes.Update, curr_t=infot) 66 | self._manager.post(EngineEvTypes.Paint, screen=engine_vars.screen) 67 | self._manager.update() 68 | gamedev_api.flip() 69 | 70 | def exit(self, vms=None): 71 | gamedev_api.close_game() 72 | 73 | def loop(self): 74 | """ 75 | its forbidden to call .loop() in the web ctx, but its convenient in the local ctx 76 | if one wants to test a program without using the Kata VM 77 | :return: 78 | """ 79 | # lock mechanism, for extra safety so we never call .loop() in the web ctx 80 | if self.SAFETY_LOCK: 81 | raise ValueError(self.ERR_LOCK_MSG) 82 | 83 | # use enter, update, exit to handle the global "run game logic" 84 | self.enter() 85 | 86 | while not self.gameover: 87 | infot = time.time() 88 | self.update(infot) 89 | self.exit() 90 | print(self.INFO_STOP_MSG) 91 | -------------------------------------------------------------------------------- /src/pyved_engine/compo/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/src/pyved_engine/compo/__init__.py -------------------------------------------------------------------------------- /src/pyved_engine/compo/modes.py: -------------------------------------------------------------------------------- 1 | from ..Singleton import Singleton 2 | from ..util import drawtext 3 | 4 | 5 | @Singleton 6 | class GameModeMger: 7 | def __init__(self): 8 | self.menus = dict() 9 | self._mode = self.menu = None 10 | 11 | @property 12 | def mode(self): 13 | return self._mode 14 | 15 | def set_curr_mode(self, mode_name): 16 | self._mode = mode_name 17 | self.menu = self.menus[mode_name] 18 | 19 | def register(self, dictobj): 20 | self.menus.update(dictobj) 21 | 22 | def switch_mode(self, mode, reset=False): 23 | if mode in self.menus: 24 | self._mode = mode 25 | self.menu = self.menus[self.mode] 26 | if reset: 27 | self.menu.__init__(self.menu.name) 28 | 29 | def update(self, events): 30 | self.menu.update(events) 31 | 32 | def draw(self, surf): 33 | self.menu.draw(surf) 34 | 35 | 36 | class BaseGameMode: 37 | """ 38 | Base signature for all menus 39 | """ 40 | 41 | def __init__(self, name='menu'): 42 | self._manager = GameModeMger.instance() 43 | self.name = name 44 | 45 | def update(self, events): # list[pygame.event.Event]): 46 | pass 47 | 48 | def draw(self, surf): 49 | surf.blit(drawtext(self.name, aliased=True), (50, 50)) 50 | -------------------------------------------------------------------------------- /src/pyved_engine/compo/vscreen.py: -------------------------------------------------------------------------------- 1 | from ..foundation import defs 2 | from .. import vars 3 | 4 | 5 | _vsurface = None 6 | _vsurface_required = True 7 | 8 | cached_pygame_mod = None # init from outside when one calls kengi.bootstrap_e 9 | special_flip = 0 # flag, set it to 1 when using web ctx 10 | stored_upscaling = 1 11 | defacto_upscaling = None 12 | 13 | # hopefully i will be able to simplify this: 14 | ctx_emuvram = None 15 | canvas_emuvram = None 16 | canvas_rendering = None 17 | real_pygamescreen = None 18 | screen_rank = 1 # so we can detect whenever its required to update the var in the PAINT engine event 19 | 20 | 21 | def set_upscaling(new_upscal_val): 22 | global stored_upscaling, _vsurface_required 23 | if stored_upscaling is not None: 24 | if int(stored_upscaling) != new_upscal_val: 25 | stored_upscaling = int(new_upscal_val) 26 | _vsurface_required = True 27 | 28 | 29 | def flip(): 30 | global _vsurface_required, _vsurface 31 | if _vsurface_required: 32 | # TODO 33 | pass 34 | 35 | if not special_flip: # flag can be off if the extra blit/transform has to disabled (web ctx) 36 | realscreen = cached_pygame_mod.display.get_surface() 37 | if 1 == stored_upscaling: 38 | realscreen.blit(vars.screen, (0, 0)) 39 | else: 40 | cached_pygame_mod.transform.scale(vars.screen, defs.STD_SCR_SIZE, realscreen) 41 | 42 | cached_pygame_mod.display.update() 43 | 44 | 45 | # ------------------------------------ 46 | # old code 47 | # ------------------------------------ 48 | _curr_state = None 49 | _loaded_states = dict() 50 | init2_done = False 51 | state_stack = None 52 | 53 | 54 | def conv_to_vscreen(x, y): 55 | return int(x / defacto_upscaling), int(y / defacto_upscaling) 56 | 57 | 58 | # def set_canvas_rendering(jsobj): 59 | # shared.canvas_rendering = jsobj 60 | # 61 | # 62 | # def set_canvas_emu_vram(jsobj): 63 | # shared.canvas_emuvram = jsobj 64 | # shared.ctx_emuvram = jsobj.getContext('2d') 65 | 66 | 67 | def set_realpygame_screen(ref_surf): 68 | global real_pygamescreen 69 | if real_pygamescreen: 70 | print('warning: set_realpygame_scneen called a 2nd time. Ignoring request') 71 | return 72 | real_pygamescreen = ref_surf 73 | 74 | 75 | def set_virtual_screen(ref_surface): 76 | global screen_rank, defacto_upscaling 77 | vars.screen = ref_surface 78 | w = vars.screen.get_size()[0] 79 | defacto_upscaling = 960/w 80 | screen_rank += 1 81 | 82 | 83 | def proj_to_vscreen(xy_pair): 84 | global stored_upscaling 85 | if stored_upscaling == 1: 86 | return xy_pair 87 | x, y = xy_pair 88 | return x//stored_upscaling, y//stored_upscaling 89 | -------------------------------------------------------------------------------- /src/pyved_engine/core/Injector.py: -------------------------------------------------------------------------------- 1 | """ 2 | PATTERN: dependency injection 3 | """ 4 | import importlib.util 5 | 6 | 7 | class _PyModulePromise: 8 | verbose = 1 9 | 10 | def __init__(self, mod_name: str, pypath: str, pck_arg: str): 11 | self._ref_module = None 12 | self._module_name = mod_name 13 | self._py_path = pypath 14 | self.pck_arg = pck_arg 15 | 16 | def is_ready(self): 17 | return self._ref_module is not None 18 | 19 | @property 20 | def name(self): 21 | return self._module_name 22 | 23 | @property 24 | def result(self): 25 | if not self.is_ready(): 26 | self._jit_load_module_op(self.pck_arg) 27 | return self._ref_module 28 | 29 | def _jit_load_module_op(self, pck_arg): 30 | nam = self.name 31 | if self.__class__.verbose and nam != 'pygame': # print a debug info. 32 | print(f' lazy loading: {nam}') 33 | if (pck_arg is not None) and self._py_path[0] == '.': 34 | self._ref_module = importlib.import_module(self._py_path, pck_arg) 35 | else: 36 | self._ref_module = importlib.import_module(self._py_path) 37 | 38 | 39 | class Injector: 40 | """ 41 | gere chargement composants engine + any engine plugin 42 | Le fait au moyen dun tableau: 43 | module name <-> instance of LazyModule 44 | """ 45 | 46 | def __init__(self, module_listing, package_arg): 47 | self._listing = dict() 48 | for mname, pypath in module_listing.items(): 49 | obj = _PyModulePromise(mname, pypath, package_arg) 50 | self._listing[obj.name] = obj 51 | self._man_set = dict() 52 | self._loading_done = False 53 | 54 | def hack_package_arg(self, new_val): # useful for the katasdk 55 | for prom_obj in self._listing.values(): 56 | prom_obj.pck_arg = new_val 57 | 58 | def __contains__(self, item): 59 | if item in self._man_set: 60 | return True 61 | else: 62 | return item in self._listing 63 | 64 | def set(self, mname, pymod): 65 | self._man_set[mname] = pymod 66 | 67 | def __getitem__(self, item): 68 | if item in self._man_set: 69 | return self._man_set[item] 70 | else: 71 | res = self._listing[item].result 72 | self._loading_done = True 73 | return res 74 | 75 | def is_loaded(self, pckname): 76 | return self._listing[pckname].is_ready() 77 | 78 | def register(self, sm_name, py_path, pck_arg): 79 | if self._loading_done: 80 | print('***warning*** register plugin should be done before using loading elements') 81 | self._listing[sm_name] = _PyModulePromise(sm_name, py_path, pck_arg) 82 | -------------------------------------------------------------------------------- /src/pyved_engine/core/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/src/pyved_engine/core/__init__.py -------------------------------------------------------------------------------- /src/pyved_engine/core/legacy_evs.py: -------------------------------------------------------------------------------- 1 | """ 2 | surcouche à pygame permettant d'utiliser l'ancien système d'évents, 3 | sans rendre fort le lien à pygame & sans dépendance forte à l'API de pygame 4 | """ 5 | from .. import _hub 6 | 7 | 8 | def get(): # direct access to the pygame event system 9 | return _hub.pygame.event.get() 10 | 11 | 12 | def pressed_keys(): # direct access to the pygame key.get_pressed() 13 | return _hub.pygame.key.get_pressed() 14 | 15 | 16 | def __getattr__(keyname): 17 | try: 18 | return getattr(_hub.pygame, keyname) 19 | 20 | except AttributeError: 21 | print('cannot find the specified key:', keyname) 22 | -------------------------------------------------------------------------------- /src/pyved_engine/evsys0.py: -------------------------------------------------------------------------------- 1 | """ 2 | replica of the pygame legacy event sys 3 | """ 4 | from . import _hub 5 | 6 | 7 | def get(): 8 | return _hub.pygame.event.get() 9 | 10 | 11 | def pressed_keys(): 12 | return _hub.pygame.key.get_pressed() 13 | 14 | 15 | def __getattr__(name): # expose(->like forwarding) all pygame key codes & pygame constants 16 | if name == 'QUIT': 17 | return _hub.pygame.QUIT 18 | try: 19 | return getattr(_hub.pygame.key, name) 20 | except AttributeError: 21 | return getattr(_hub.pygame, name) 22 | -------------------------------------------------------------------------------- /src/pyved_engine/foundation/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/src/pyved_engine/foundation/__init__.py -------------------------------------------------------------------------------- /src/pyved_engine/foundation/interfaces.py: -------------------------------------------------------------------------------- 1 | """ 2 | Licensed code LGPL 3 3 | (c) 2018-2024, to the Kata.Games company 4 | 5 | TL;DR - Pyved is not using 100% of pygame functions. 6 | So how much of pygame do we use? 7 | 8 | More precisely: this file is here so I can: 9 | (A) specify (for this I propose an informal interface) a SUBSET of pygame 10 | 11 | (B) offer a formal interface for the so-called "PRIMAL backend". Such a backend can 12 | be implemented in various ways. Interestingly, one possible way is to use a SUBSET of pygame. 13 | Since I consider that it wouldn't be great to use a subset of pygame without "exposing" it 14 | to the end-user too (pygame is a nice tool, after all) 15 | it is decided that the subset used is equal to the one I specified in A. 16 | 17 | Having a formal interface is important as it enables me to "plug" into a different system/ 18 | another software environment. Components like KENGI, the KataSDK, etc. need to be 19 | adaptive because at the end of the day, we wish to execute games in a browser. 20 | """ 21 | 22 | from abc import abstractmethod, ABCMeta 23 | 24 | 25 | class BaseKenBackend(metaclass=ABCMeta): 26 | @abstractmethod 27 | def fetch_kengi_events(self): 28 | raise NotImplementedError 29 | 30 | @abstractmethod 31 | def joystick_init(self, idj): 32 | raise NotImplementedError 33 | 34 | @abstractmethod 35 | def joystick_info(self, idj): 36 | raise NotImplementedError 37 | 38 | @abstractmethod 39 | def joystick_count(self): 40 | raise NotImplementedError 41 | 42 | 43 | class _pygameDrawIface: 44 | 45 | @staticmethod 46 | def circle(surface, color, pos, radius): 47 | pass 48 | 49 | @staticmethod 50 | def rect(surface, bidule): 51 | pass 52 | 53 | 54 | class _pygameMathIface: 55 | 56 | def Vector2(self, **args): 57 | pass 58 | 59 | 60 | class PygameIface: 61 | 62 | draw = _pygameDrawIface 63 | math = _pygameMathIface 64 | 65 | KEYDOWN = -1 66 | KEYUP = 2 67 | K_LEFT = 3 68 | 69 | @staticmethod 70 | def Color(rgb): 71 | pass 72 | -------------------------------------------------------------------------------- /src/pyved_engine/gamedev_api/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tom said: in a perfect world the gamedev_api should be structures like this: 3 | 4 | - __init__: stores the list of all functions and classes that concretize the API 5 | (it should be obvious that this file's sole purpose is to select objects from engine_logic, as well as 6 | objects from highlevel_func and expose them nicely) 7 | 8 | - highlevel_func: implementations that exist at a such high level of abstraction that the ctx doesnt matter 9 | - context_bridge: basically a container for implementations that can be replaced, based on the ctx 10 | (->dependency injection pattern) 11 | 12 | - engine_logic: stores the general state of the engine, how the engine transitions from 1 state to another, etc. 13 | (functions such as init are defined here because they indeed modify the engine state. This file imports the 14 | two modules mentionned above) 15 | """ 16 | # TODO refactoring 17 | -------------------------------------------------------------------------------- /src/pyved_engine/gamedev_api/local_context.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def engine_init(mode): 4 | print('engine_init local context!') 5 | 6 | 7 | def machin(): 8 | print('machin local context!') 9 | 10 | 11 | def flip(): 12 | print('flip local context!') 13 | -------------------------------------------------------------------------------- /src/pyved_engine/looparts/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | all elements in this sub-modules are imported directly 3 | 4 | via Injector 5 | (dependency injection manager) 6 | 7 | use the: 8 | 9 | import katagames_sdk.engine as kataen 10 | kataen.* 11 | 12 | syntax 13 | """ 14 | 15 | # N.b need to import so setup.py can detect all files 16 | # from . import console 17 | # from . import rogue 18 | # from . import tabletop 19 | # from . import terrain 20 | -------------------------------------------------------------------------------- /src/pyved_engine/looparts/ai/__init__.py: -------------------------------------------------------------------------------- 1 | from . import tests 2 | from . import NorrecBrain 3 | from . import FSA_classes_base 4 | -------------------------------------------------------------------------------- /src/pyved_engine/looparts/ai/tests.py: -------------------------------------------------------------------------------- 1 | from .NorrecBrain import NorrecBrain 2 | 3 | 4 | def run_test(): 5 | npcs2class = { 6 | 'norrec': NorrecBrain 7 | } 8 | curr_npc_name = 'norrec' 9 | pnj_courant = npcs2class[curr_npc_name]() # build npc instance 10 | CODE_EXIT = 'Q' 11 | 12 | # print tutorial 13 | print("simulateur de dialogue, à tout moment vous pouvez saisir '" + CODE_EXIT + "' pour quitter") 14 | print("le dialogue commence...") 15 | print('\n' + '-'*44) 16 | 17 | # loop 18 | SYM_PROMPT = '>>> ' 19 | pnj_courant.say_something() 20 | saisie = input(SYM_PROMPT) 21 | while saisie != CODE_EXIT: 22 | pnj_courant.entree_info(saisie) 23 | pnj_courant.say_something() 24 | saisie = input(SYM_PROMPT) 25 | print('done!') 26 | -------------------------------------------------------------------------------- /src/pyved_engine/looparts/demolib/__init__.py: -------------------------------------------------------------------------------- 1 | from . import animobs 2 | from . import dialogue 3 | from . import pathfinding 4 | from . import rpgmenu 5 | -------------------------------------------------------------------------------- /src/pyved_engine/looparts/isometric/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Barebones isometric_map handling for an isometric RPG. For game-specific data, 3 | either subclass the Scene or just declare whatever extra bits are needed. 4 | """ 5 | 6 | from .IsometricMapViewer import IsometricMapViewer 7 | from .IsometricMapViewer0 import IsometricMapViewer0 8 | # from . import extras 9 | from . import model 10 | from .extras import IsometricMapQuarterCursor as IsoCursor 11 | 12 | 13 | def set_tiled_version(vernum): 14 | if float(vernum) < 1.9: 15 | model.info_type_obj = 'type' 16 | print('*LEGACY isometric model ON*') 17 | -------------------------------------------------------------------------------- /src/pyved_engine/looparts/isometric/flags.py: -------------------------------------------------------------------------------- 1 | 2 | # used in the project 3 | NOT_ALL_FLAGS = 0x0FFFFFFF 4 | FLIPPED_HORIZONTALLY_FLAG = 0x80000000 5 | FLIPPED_VERTICALLY_FLAG = 0x40000000 6 | 7 | # not used so far (june 9th) 8 | FLIPPED_DIAGONALLY_FLAG = 0x20000000 9 | ROTATED_HEXAGONAL_120_FLAG = 0x10000000 10 | -------------------------------------------------------------------------------- /src/pyved_engine/looparts/isometric/isosm_config.py: -------------------------------------------------------------------------------- 1 | 2 | SCROLL_STEP = 0.25 3 | FLIPPED_HORIZONTALLY_FLAG = 0x80000000 4 | FLIPPED_VERTICALLY_FLAG = 0x40000000 5 | FLIPPED_DIAGONALLY_FLAG = 0x20000000 6 | ROTATED_HEXAGONAL_120_FLAG = 0x10000000 7 | NOT_ALL_FLAGS = 0x0FFFFFFF 8 | -------------------------------------------------------------------------------- /src/pyved_engine/looparts/polarbear/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | (~*~ legacy code ~*~) 3 | AUTHOR INFO 4 | Joseph H. cf. https://github.com/jwvhewitt 5 | 6 | LICENSE INFO 7 | for the whole polarbear folder: Apache 2.0 8 | 9 | Below are chunks extracted from the Polar Bear Game Engine. 10 | This package contains some low-level graphics stuff needed to 11 | create an isometric RPG style rules in Python. The idea is to 12 | isolate the graphics handling from the code as much as possible, 13 | so that if PyGame is replaced the interface shouldn't change 14 | too much. Also, so that creating a new rules should be as simple 15 | as importing this package. 16 | Word wrapper taken from the PyGame wiki plus the list-printer 17 | from Anne Archibald's GearHead Prime demo. 18 | """ 19 | 20 | from . import image 21 | from . import widgets 22 | from .general import default_border, render_text, wait_event, TIMEREVENT, INFO_GREEN 23 | from .image import draw_text 24 | -------------------------------------------------------------------------------- /src/pyved_engine/looparts/polarbear/frects.py: -------------------------------------------------------------------------------- 1 | from ... import _hub 2 | from ... import vars 3 | 4 | 5 | ANCHOR_UPPERLEFT = (0, 0) 6 | ANCHOR_UPPERRIGHT = (2, 0) 7 | ANCHOR_CENTER = (1, 1) 8 | ANCHOR_LOWERLEFT = (0, 2) 9 | ANCHOR_LOWERRIGHT = (2, 2) 10 | ANCHOR_TOP = (1, 0) 11 | ANCHOR_LEFT = (0, 1) 12 | ANCHOR_RIGHT = (2, 1) 13 | 14 | pygame = _hub.pygame 15 | 16 | 17 | class Frect(object): 18 | """Floating rect- changes position depending on the screen dimensions.""" 19 | 20 | def __init__(self, dx, dy, w, h, anchor=ANCHOR_CENTER, parent=None): 21 | self.dx = dx 22 | self.dy = dy 23 | self.w = w 24 | self.h = h 25 | self.anchor = anchor 26 | self.parent = parent 27 | 28 | def get_rect(self): 29 | if self.parent: 30 | prect = self.parent.get_rect() 31 | x0 = prect.left + (prect.w // 2) * self.anchor[0] 32 | y0 = prect.top + (prect.h // 2) * self.anchor[1] 33 | else: 34 | sw, sh = vars.screen.get_size() 35 | x0 = (sw // 2) * self.anchor[0] 36 | y0 = (sh // 2) * self.anchor[1] 37 | return pygame.Rect(self.dx + x0, self.dy + y0, self.w, self.h) 38 | -------------------------------------------------------------------------------- /src/pyved_engine/looparts/sysconsole.py: -------------------------------------------------------------------------------- 1 | from .. import _hub 2 | 3 | pygame = _hub.pygame 4 | 5 | 6 | class MiniConsComponent: 7 | """ 8 | contains: 9 | - minimalistic model to handle the cursor pos 10 | + {backspace key; delete key; carret return} 11 | - a flush method that takes care of everything 12 | (useful to call everything that's internal to kengi.ascii) 13 | """ 14 | CONS_DISP_OFFSET = (1, 1) # cannot use 0 bc its a border! 15 | 16 | def __init__(self, txtcolor): 17 | self.txtcolor = txtcolor 18 | self.fgcolor = txtcolor 19 | self.bgcolor = None # for text ! 20 | 21 | # the model per se 22 | self.needs_paint_op = False 23 | self.logical_cursor_pos = [0, 0] 24 | bounds = _hub.ascii.get_bounds() 25 | self.maxlines = bounds[1] - 2 # see above, almost same remark 26 | self.alltext = '' 27 | self.lines = list() 28 | self._nblines = 0 29 | self._buffer = list() 30 | self._prev_t = None 31 | 32 | def draw_console_line(self, myword, base_ij_pos): 33 | for rank, mchar in enumerate(myword): 34 | _hub.ascii.put_char(mchar, (base_ij_pos[0] + rank, base_ij_pos[1]), self.fgcolor, self.bgcolor) 35 | 36 | def lineappend(self, line_of_text): 37 | """ 38 | for better results, use full lines! Its buffered bc we wanna 39 | add it line per line and display before adding the nxt one 40 | """ 41 | self._buffer.append(line_of_text) 42 | 43 | def has_bufferempty(self): 44 | return len(self._buffer) == 0 45 | 46 | def update(self, infot): 47 | if len(self._buffer): 48 | self._prev_t = infot 49 | self.lines.append(self._buffer.pop(0)) 50 | self.needs_paint_op = True 51 | 52 | def draw(self): 53 | # push the whole set of chars to screen & refresh display 54 | _hub.ascii.reset() 55 | if len(self.lines) > self.maxlines: 56 | k = self.maxlines 57 | plines = self.lines[-k:] # last k lines 58 | else: 59 | plines = self.lines 60 | for j, line_content in enumerate(plines): 61 | self.draw_console_line( # since we dont use bgcolor => pass None 62 | line_content, (self.CONS_DISP_OFFSET[0], self.CONS_DISP_OFFSET[1] + j) 63 | ) 64 | _hub.ascii.flush() 65 | self.needs_paint_op = False 66 | -------------------------------------------------------------------------------- /src/pyved_engine/util.py: -------------------------------------------------------------------------------- 1 | import re 2 | from . import _hub 3 | from pathlib import Path 4 | 5 | 6 | FONT = 'consolas' 7 | 8 | 9 | def _font(size): 10 | return _hub.kengi_inj['pygame'].font.SysFont(FONT, size) 11 | 12 | 13 | def camel_case_format(string_ac_underscores): 14 | words = [word.capitalize() for word in string_ac_underscores.split('_')] 15 | return "".join(words) 16 | 17 | 18 | def drawtext(msg, size=50, color=(255, 255, 255), aliased=False): 19 | return _font(size).render(msg, aliased, color) 20 | 21 | 22 | def underscore_format(name): 23 | s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name) 24 | return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower() 25 | 26 | 27 | def path_to_img_infos(filepath): 28 | """ 29 | :param filepath: for example /users/tom/machin.png 30 | :return: both the future image name(identifier) that is "machin" and a filename thing to load: "machin.png" 31 | """ 32 | pobj = Path(filepath) 33 | return pobj.stem, pobj.name 34 | -------------------------------------------------------------------------------- /src/pyved_engine/vars.py: -------------------------------------------------------------------------------- 1 | """ 2 | Public variables tied to the game engine. 3 | 4 | WARNING: Although these variables can be accesed directly, it is NOT recommended 5 | to tweak these values manually. 6 | Unexpected outcomes/side-effects could be produced by doing so. 7 | Instead use functions like pyv.preload_assets(...) or init(max_fps=..., ...) etc. 8 | """ 9 | 10 | 11 | # below is a read-only value, 12 | # to retrieve this value from outside you can call pyv.get_version() 13 | ENGINE_VERSION_STR = '25.1a1' 14 | 15 | DATA_FT_SIZE = 16 16 | 17 | # deprecated but mandatory for web ctx 18 | STD_SCR_SIZE = [960, 720] 19 | 20 | # - engine related 21 | disp_size = [960, 720] 22 | 23 | backend_name = '' # type str, and the default value is '' but it could be modified from elsewhere 24 | weblib_sig = None 25 | 26 | clock = None # at some point, this should store a ref on an Obj. typed pygame.time.Clock 27 | max_fps = 45 # will be replaced by whatever is passed to pyv.init(...) 28 | screen = None 29 | 30 | # - game related (universal behavior) 31 | # 4 vars in order to handle all game assets 32 | images = dict() 33 | fonts = dict() 34 | spritesheets = dict() 35 | sounds = dict() 36 | csvdata = dict() 37 | data = dict() # for raw json, most of the time 38 | 39 | # 4 vars to handle the game loop conveniently 40 | gameover = False 41 | beginfunc_ref = updatefunc_ref = endfunc_ref = None 42 | -------------------------------------------------------------------------------- /tests/cards_testing.py: -------------------------------------------------------------------------------- 1 | import pyved_engine as pyv 2 | 3 | pyv.bootstrap_e() 4 | 5 | 6 | # aliases 7 | StdCard = pyv.tabletop.StandardCard 8 | PokerHand = pyv.tabletop.PokerHand 9 | pygame = pyv.pygame 10 | 11 | 12 | # ----------------- debug strength of cards ------------------ 13 | # pl_cards = [ 14 | # StdCard('8d'), 15 | # StdCard('3s'), 16 | # ] 17 | # dealer_cards = [ 18 | # StdCard('5h'), 19 | # StdCard('Th'), 20 | # ] 21 | # shared_cards = [ 22 | # StdCard('4s'), 23 | # StdCard('Qh'), 24 | # StdCard('Kh'), 25 | # StdCard('Kd'), 26 | # StdCard('As') 27 | # ] 28 | # dhand = pyv.tabletop.find_best_ph(dealer_cards+shared_cards) 29 | # phand = pyv.tabletop.find_best_ph(pl_cards+shared_cards) 30 | # print(dhand, '\n', phand) 31 | # print(dhand.value, '\n', phand.value) 32 | # print(phand.value > dhand.value) 33 | # import sys 34 | # sys.exit(0) 35 | 36 | 37 | # OMEGA_SYM = ('2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A') OMEGA_SUIT = ('c', 'd', 'h', 's') 38 | lcards = [ 39 | StdCard('Tc'), 40 | StdCard('Jc'), 41 | StdCard('Qc'), 42 | StdCard('Kc'), 43 | StdCard('Ac'), 44 | ] 45 | # print(lcards[-1].numeric) 46 | 47 | p_hand = pyv.tabletop.PokerHand(lcards) 48 | str_fulsh = p_hand.is_royal() # p_hand.is_straight() and p_hand.is_flush() 49 | # print(' ---', str_fulsh) 50 | 51 | # print(p_hand) 52 | # print(p_hand.value) 53 | 54 | # - le chargement des assets se fait comme ceci: 55 | spr_sheet = pyv.gfx.JsonBasedSprSheet('cartes') 56 | my_assets = dict() 57 | for card_cod in StdCard.all_card_codes(): 58 | y = PokerHand.adhoc_mapping(card_cod[0]).lstrip('0') + card_cod[1].upper() # convert card code to path 59 | my_assets[card_cod] = spr_sheet[f'{y}.png'] 60 | 61 | print() 62 | print('*'*48) 63 | print('[ Instructions: press space to randomize cards dealt, ESC key to quit ]') 64 | print() 65 | print('The strength of your hand now= ', p_hand.value) 66 | 67 | 68 | class MaquetteJc(pyv.GameTpl): 69 | def list_game_events(self): 70 | return None 71 | 72 | def get_video_mode(self): 73 | return 2 74 | 75 | def update(self, infot): 76 | global lcards, p_hand 77 | # - event detection facon pygame 78 | for e in pygame.event.get(): 79 | if e.type == pygame.KEYDOWN: 80 | if e.key == pygame.K_SPACE: 81 | # new draw of cards 82 | lcards = [pyv.tabletop.StandardCard.at_random() for _ in range(5)] 83 | p_hand = PokerHand(lcards) 84 | print('The strength of your hand now= ', p_hand.value) 85 | elif e.key == pygame.K_ESCAPE: 86 | self.gameover = True 87 | 88 | # - maj graphique 89 | pyv.get_surface().fill('darkgreen') 90 | images = list() 91 | for card_obj in p_hand: 92 | images.append(my_assets[card_obj.code]) 93 | 94 | for k, img in enumerate(images): 95 | pyv.get_surface().blit(img, (32+k*55, 256) ) 96 | pyv.flip() 97 | 98 | 99 | g = MaquetteJc() 100 | g.loop() 101 | -------------------------------------------------------------------------------- /tests/cartes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyved-solution/pyved-engine/f4b2f1fbd0ed4c6ab2271e554115a8203a04ea0c/tests/cartes.png -------------------------------------------------------------------------------- /tests/cb_test.py: -------------------------------------------------------------------------------- 1 | import pyved_engine as pyv 2 | 3 | 4 | CircularBuffer = pyv.CircularBuffer 5 | 6 | cb = CircularBuffer(3) 7 | print(str(cb)) 8 | print("Empty: {}".format(cb.is_empty())) 9 | print("Full: {}".format(cb.is_full())) 10 | print() 11 | 12 | cb.enqueue("one") 13 | cb.enqueue("two") 14 | cb.enqueue("three") 15 | cb.enqueue("four") 16 | print(str(cb)) 17 | print("Empty: {}".format(cb.is_empty())) 18 | print("Full: {}".format(cb.is_full())) 19 | print() 20 | 21 | print(cb.dequeue()) 22 | 23 | print('front?', cb.front()) 24 | print(str(cb)) 25 | print(cb.get_size()) 26 | print("Empty: {}".format(cb.is_empty())) 27 | print("Full: {}".format(cb.is_full())) 28 | print() 29 | 30 | cb.enqueue("five") 31 | cb.enqueue("six") 32 | print(str(cb)) 33 | print('front? ', cb.front()) 34 | print(cb.get_size()) 35 | print("Empty: {}".format(cb.is_empty())) 36 | print("Full: {}".format(cb.is_full())) 37 | print() 38 | 39 | print(cb.dequeue()) 40 | print(cb.dequeue()) 41 | print(cb.dequeue()) 42 | print(str(cb)) 43 | print(cb.get_size()) 44 | print("Empty: {}".format(cb.is_empty())) 45 | print("Full: {}".format(cb.is_full())) 46 | -------------------------------------------------------------------------------- /tests/evsys4_test.py: -------------------------------------------------------------------------------- 1 | """ 2 | testing the event system rev4 3 | """ 4 | import pyved_engine as pyv 5 | 6 | EvManager = pyv.events.EvManager 7 | PseudoEnum = pyv.events.PseudoEnum 8 | EngineEvTypes = pyv.events.EngineEvTypes 9 | game_events_enum = pyv.events.game_events_enum 10 | 11 | 12 | class SampleListener(pyv.EvListener): 13 | """ 14 | mockup class 15 | """ 16 | def __init__(self, nom): 17 | super().__init__() 18 | self._avname = nom 19 | 20 | def get_av_name(self): 21 | return self._avname 22 | 23 | def set_av_name(self, x): 24 | self._avname = x 25 | 26 | def on_paint(self, ev): 27 | print('m1 -', self, ev) 28 | 29 | def on_player_death(self, ev): 30 | print('m1 -', self, ev) 31 | 32 | def on_update(self, ev): 33 | print('m2 -', self, ev) 34 | 35 | def on_netw_receive(self, ev): 36 | print('m3 -', self, ev) 37 | 38 | def __str__(self): 39 | return '' 40 | 41 | 42 | # ----------------- 43 | # testing 44 | # ---------------- 45 | pyv.init() 46 | 47 | MyEvents = game_events_enum(( 48 | 'PlayerMovement', 49 | 'PlayerDeath' 50 | )) 51 | 52 | manager = EvManager.instance() 53 | manager.debug_mode = True 54 | 55 | # the manager becomes "self-aware", for 56 | # all engine ev types AND all game-specific ev types 57 | manager.setup(MyEvents) 58 | 59 | print('~~ codes ~~') 60 | print(EngineEvTypes.Update) 61 | print(EngineEvTypes.Paint) 62 | print('...') 63 | print(EngineEvTypes.NetwReceive) 64 | print('and the extra:') 65 | print(MyEvents.PlayerMovement) 66 | print(MyEvents.PlayerDeath) 67 | print('-' * 48) 68 | 69 | # Test: post 5 events and updates the ev manager... 70 | print('method .POST called x5') 71 | manager.post(17, serveur='api.gaudia-tech.com', machin='ouais') 72 | manager.post(3, jojo='trois', nom='tom') 73 | manager.post(551, hp='128', nom='roger') 74 | manager.post(17, hp='11', nom='jojo') 75 | manager.post(332, hp='59878', nom='poisson') 76 | 77 | print('the NEW queue size=', manager.queue_size) 78 | manager.update() 79 | print('after .UPDATE call, the queue size=', manager.queue_size) 80 | print('-' * 48) 81 | 82 | print('show me the regexp in EventManager inst?') 83 | print(manager.regexp) 84 | print(manager.regexp.match('on_player_movement')) 85 | print('-' * 48) 86 | 87 | print("create! then turn on/turn off the listener..") 88 | my_li = SampleListener('thomas') 89 | print('listener id?', my_li.id) 90 | my_li.turn_on() 91 | my_li.turn_off() 92 | 93 | # ---for sandbox testing--- 94 | pyv.quit() 95 | enum_example = PseudoEnum(['KeyUp', 'KeyDown', 'Update']) 96 | print(enum_example.KeyUp) 97 | -------------------------------------------------------------------------------- /tests/evsys6_test.py: -------------------------------------------------------------------------------- 1 | """ 2 | placeholder. We will need to test the new event system (v6) soon 3 | """ -------------------------------------------------------------------------------- /tests/rpg_testing.py: -------------------------------------------------------------------------------- 1 | import pyved_engine as pyv 2 | 3 | 4 | pyv.bootstrap_e() 5 | 6 | 7 | class RpgActuator(pyv.EvListener): 8 | def __init__(self, refgame): 9 | super().__init__() 10 | self._game = refgame 11 | self._av_model = ( 12 | pyv.rpg.Character('Erydram', level=13, maxhp=115, health=0.88, str=25, int=22, charisma=5, luck=3), 13 | pyv.rpg.Weapon('longsword', damage='2-9', req='str:8') 14 | ) 15 | for obj in self._av_model: 16 | print(obj) 17 | self._opponent_model = ( 18 | pyv.rpg.Character('Goblin', level=5, maxhp=100, str=8, int=1, charisma=2, luck=5), 19 | ) 20 | print(self._opponent_model[0]) 21 | 22 | def on_paint(self, ev): 23 | ev.screen.fill('antiquewhite2') 24 | pyv.flip() 25 | 26 | def on_quit(self, ev): 27 | self._game.gameover = True 28 | 29 | 30 | class MyRpg(pyv.GameTpl): 31 | def get_video_mode(self): 32 | return pyv.LOW_RES_MODE 33 | 34 | def list_game_events(self): 35 | return None 36 | 37 | def enter(self, vms=None): 38 | super().enter(vms) 39 | RpgActuator(self).turn_on() 40 | 41 | 42 | g = MyRpg() 43 | g.loop() 44 | -------------------------------------------------------------------------------- /tests/struct_tree.py: -------------------------------------------------------------------------------- 1 | import pyved_engine as pyv 2 | 3 | TreeNode = pyv.struct.TreeNode 4 | 5 | 6 | x = TreeNode('salut xy', None) 7 | my_tree = x.tree_ref 8 | y = TreeNode(88, x) 9 | z = TreeNode(15, y) 10 | 11 | print(' should print:\n0 1 2') 12 | print(x.depth, y.depth, z.depth) 13 | 14 | print(' should print:\nFalse False True False 1 0') 15 | print(y.is_root(), x.is_leaf(), z.is_leaf(), y.is_leaf(), y.child_count, z.child_count) 16 | 17 | print(' should print:\n2 2 5') 18 | kappa = TreeNode(128, y) 19 | ultima = kappa.tree_ref.append_value(129, kappa) 20 | print(kappa.depth, y.child_count, my_tree.count) 21 | 22 | print(' should print:\nsalut xy') 23 | print(my_tree.root.value) 24 | 25 | print(' should print:\n-same object ref twice-') 26 | print(my_tree.node_by_content(129), ultima) 27 | 28 | print(' should print:\nNone') 29 | print(my_tree.node_by_content('lol')) 30 | 31 | print('*****************') 32 | print('*****************') 33 | print(my_tree) 34 | -------------------------------------------------------------------------------- /tests/test_engine.py: -------------------------------------------------------------------------------- 1 | import pyved_engine as pyv 2 | 3 | 4 | HELP_MSG = 'press ESC to exit, any key to change bg_color...' 5 | CAPTION = 'my first video game, hi mom!' 6 | 7 | 8 | pyv.init(1, wcaption=CAPTION) 9 | pygame = pyv.pygame 10 | screen = pyv.get_surface() 11 | color_idx = 0 12 | allcolors = ('pink', 'yellow', 'purple') 13 | bg_color = allcolors[0] 14 | print(HELP_MSG) 15 | gameover = False 16 | 17 | 18 | while not gameover: # game loop 19 | for ev in pygame.event.get(): 20 | if ev.type == pygame.KEYDOWN: 21 | if ev.key == pygame.K_ESCAPE: 22 | gameover = True 23 | else: 24 | color_idx = (color_idx + 1) % len(allcolors) 25 | # update "game logic" 26 | bg_color = allcolors[color_idx] 27 | # update the display 28 | screen.fill(bg_color) 29 | pyv.flip() 30 | print('done!') 31 | --------------------------------------------------------------------------------