Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,9 @@ __pycache__/
*.pyc
.coverage
htmlcov/

.venv/
venv/
venv38/

.idea
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ If you spot a bug or have an idea for enhancement, write us an GitHub issue.

### Requirements

Python v. 3.7
Python v. 3.8
We recommend to use virtual environment.

(Python version was raised from 3.7 to 3.8 for Pyglet 2)

To successfully run the project, run the script below. It will install all the requirements including additional libraries:
- [pyglet](https://bitbucket.org/pyglet/pyglet/wiki/Home) - the graphical library,
- [asyncio](https://docs.python.org/3/library/asyncio.html) and [aiohttp](https://aiohttp.readthedocs.io/en/stable/) - asynchronous frameworks to run server and clients,
Expand All @@ -47,7 +49,7 @@ You can choose a map to play directly from command line by writing the location
The same way you can enter the number of players `-p, --players`. The current maps are prepared for the max. 8 players.

```
python server.py -m maps/game_1.json -p 6
python server.py -m maps/belt_map.json -p 6
```

If you run server on a different computer than the clients, get the server's hostname and run clients with its value as the named argument `-h, --hostname`.
Expand Down
4 changes: 4 additions & 0 deletions client_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import asyncio
import aiohttp
import pyglet
pyglet.options['shadow_window'] = False

import click
from time import monotonic

Expand Down Expand Up @@ -156,6 +158,8 @@ def run_from_welcome_board(robot_name, own_robot_name, hostname):
def main(hostname, robot_name):
interface = Interface(hostname)
pyglet.clock.schedule_interval(tick_asyncio, 1/30)
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
asyncio.ensure_future(interface.get_messages(robot_name))
pyglet.app.run()

Expand Down
4 changes: 4 additions & 0 deletions client_receiver.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import asyncio
import aiohttp
import pyglet
pyglet.options['shadow_window'] = False

import click
from time import monotonic
from util_network import tick_asyncio
Expand Down Expand Up @@ -107,6 +109,8 @@ def main(hostname):
# Schedule the "client" task
# More about Futures - official documentation
# https://docs.python.org/3/library/asyncio-future.html
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
asyncio.ensure_future(receiver.get_game_state())
pyglet.app.run()

Expand Down
4 changes: 4 additions & 0 deletions client_welcome_board.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import asyncio
import aiohttp
import pyglet
pyglet.options['shadow_window'] = False

import click

from backend import State
Expand Down Expand Up @@ -97,6 +99,8 @@ def main(hostname):
# Schedule the "client" task
# More about Futures - official documentation
# https://docs.python.org/3/library/asyncio-future.html
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
asyncio.ensure_future(welcome_board.process_message())
pyglet.app.run()

Expand Down
14 changes: 8 additions & 6 deletions export_img.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import subprocess
from pathlib import Path

inkscape_paths = [
INKSCAPE_PATHS = [
"inkscape",
"C:/Program Files/Inkscape/inkscape",
"C:/Program Files (x86)/Inkscape/inkscape"
Expand All @@ -29,11 +29,11 @@ def find_inkscape_path():
"""
Return first functional Inkscape path
"""
for path in inkscape_paths:
for path in INKSCAPE_PATHS:
if run_inkscape(path):
return path

inkscape = find_inkscape_path()
INKSCAPE = find_inkscape_path()

def export_svg_png():
"""
Expand All @@ -56,7 +56,9 @@ def export_svg_png():
new_name.parent.mkdir(exist_ok=True, parents=True)
# launch Inkscape and export all images to PNG format
# More info about subprocess in official documentation - https://docs.python.org/3/library/subprocess.html
subprocess.run([inkscape, name, "--export-png=" + str(new_name), "--export-area-page"], check=True)
print(name)
subprocess.run([INKSCAPE, name, "--export-filename="+str(new_name), "--export-area-page"], check=True)

export_svg_png()
print("Done")
if __name__ == '__main__':
export_svg_png()
print("Done")
55 changes: 40 additions & 15 deletions frontend.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,61 @@
"""

import pyglet
pyglet.options['shadow_window'] = False

from pyglet.gl import Config as GLConfig
from pathlib import Path
from time import monotonic
from util_frontend import TILE_WIDTH, TILE_HEIGHT, get_label, get_sprite, window_zoom
from util_frontend import (TILE_WIDTH, TILE_HEIGHT, get_label, get_sprite, window_zoom,
_init_module_after_gl_context as _util_frontend_init_module_after_gl_context)
import math

# Loading of tiles and robots images
loaded_tiles_images = {}
for image_path in Path('./img/tiles/png').iterdir():
loaded_tiles_images[image_path.stem] = pyglet.image.load(image_path)

loaded_robots_images = {}
for image_path in Path('./img/robots_map/png').iterdir():
loaded_robots_images[image_path.stem] = pyglet.image.load(image_path)
loaded_tiles_images = {} # init inside _init_module_after_gl_context
loaded_robots_images = {} # init inside _init_module_after_gl_context

_init_module_after_gl_context_called = False

def _init_module_after_gl_context():
""" Loading of tiles and robots images
because of the gl.gl_compat functions we need to load sprites
after a window with correct GL context is created
"""
global loaded_tiles_images, loaded_robots_images
global border_sprite, winner_sprite #, game_over_sprite
global _init_module_after_gl_context_called
if _init_module_after_gl_context_called:
return
_init_module_after_gl_context_called = True

# Border of available robot's picture
border_sprite = get_sprite('./img/interface/png/border.png')
# Winner
winner_sprite = get_sprite('img/interface/png/game_winner.png', x=170, y=200)
# Game over
# game_over_sprite = get_sprite('img/interface/png/game_over.png', x=140, y=180)
for image_path in Path('./img/tiles/png').iterdir():
loaded_tiles_images[image_path.stem] = pyglet.image.load(str(image_path))

for image_path in Path('./img/robots_map/png').iterdir():
loaded_robots_images[image_path.stem] = pyglet.image.load(str(image_path))

# Border of available robot's picture
border_sprite = get_sprite('./img/interface/png/border.png')
# Winner
winner_sprite = get_sprite('img/interface/png/game_winner.png', x=170, y=200)
# Game over
# game_over_sprite = get_sprite('img/interface/png/game_over.png', x=140, y=180)


def create_window(state, on_draw):
"""
Return a pyglet window for graphic output.
Loads global sprites in the first call after the window is created with compatible GL context.

state: State object containing game board, robots and map sizes
"""
gl_config = GLConfig(major_version=2, minor_version=1, forward_compatible=False)
window = pyglet.window.Window(state.tile_count[0] * TILE_WIDTH,
state.tile_count[1] * TILE_HEIGHT + 50, resizable=True)
state.tile_count[1] * TILE_HEIGHT + 50,
config=gl_config, resizable=True)
_util_frontend_init_module_after_gl_context()
_init_module_after_gl_context()

window.push_handlers(on_draw=on_draw)
return window

Expand Down
2 changes: 2 additions & 0 deletions game.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
- choose standard or other map to be loaded
"""
import pyglet
pyglet.options['shadow_window'] = False

import sys

from backend import State
Expand Down
Loading