From bc62c5c14cf3b7b5d1cde54717002cd96e0e8cd0 Mon Sep 17 00:00:00 2001 From: Dorian Pula Date: Sat, 4 Jun 2016 11:59:40 -0700 Subject: [PATCH 01/19] Add initial screen layout. --- helloworld.kv | 6 ------ main.py | 10 ++++++---- strategygame.kv | 18 ++++++++++++++++++ 3 files changed, 24 insertions(+), 10 deletions(-) delete mode 100644 helloworld.kv create mode 100644 strategygame.kv diff --git a/helloworld.kv b/helloworld.kv deleted file mode 100644 index 97643d1..0000000 --- a/helloworld.kv +++ /dev/null @@ -1,6 +0,0 @@ - -#:include debug.kv - -: - DebugLabel: - text: 'hello world' \ No newline at end of file diff --git a/main.py b/main.py index a437177..dc2986e 100644 --- a/main.py +++ b/main.py @@ -1,12 +1,14 @@ from kivy.app import App from kivy.uix.floatlayout import FloatLayout -class HelloWorld(FloatLayout): + +class StrategyGame(FloatLayout): pass -class HelloWorldApp(App): + +class StrategyGameApp(App): def build(self): - return HelloWorld() + return StrategyGame() if __name__ == '__main__': - HelloWorldApp().run() + StrategyGameApp().run() diff --git a/strategygame.kv b/strategygame.kv new file mode 100644 index 0000000..d5b66af --- /dev/null +++ b/strategygame.kv @@ -0,0 +1,18 @@ + +#:include debug.kv + +: + BoxLayout: + orientation: 'horizontal' + DebugLabel: + text: 'Main map' + size_hint: .75, 1 + BoxLayout: + orientation: 'vertical' + size_hint: .25, 1 + DebugLabel: + text: 'status' + size_hint: 1, .66 + DebugLabel: + text: 'mini-map' + size_hint: 1, .33 From d28564bca4f61875cfdca9f340741f37159c600c Mon Sep 17 00:00:00 2001 From: Dorian Pula Date: Sat, 4 Jun 2016 12:06:41 -0700 Subject: [PATCH 02/19] Add grid layout for the hex map. --- strategygame.kv | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/strategygame.kv b/strategygame.kv index d5b66af..8fd52a0 100644 --- a/strategygame.kv +++ b/strategygame.kv @@ -2,10 +2,12 @@ #:include debug.kv : + main_map: _main_map BoxLayout: orientation: 'horizontal' - DebugLabel: - text: 'Main map' + GridLayout: + id: _main_map + cols: 10 size_hint: .75, 1 BoxLayout: orientation: 'vertical' From 57b8de4470f4d09d950d4d84e1a831f838d032af Mon Sep 17 00:00:00 2001 From: Dorian Pula Date: Sat, 4 Jun 2016 12:23:40 -0700 Subject: [PATCH 03/19] Add grid layout with coordinates for map. --- main.py | 15 ++++++++++++++- strategygame.kv | 6 +++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/main.py b/main.py index dc2986e..ab87f7a 100644 --- a/main.py +++ b/main.py @@ -1,9 +1,22 @@ from kivy.app import App +from kivy import properties +from kivy.uix import button from kivy.uix.floatlayout import FloatLayout class StrategyGame(FloatLayout): - pass + main_map = properties.ObjectProperty(None) + map_rows = properties.NumericProperty(0) + map_cols = properties.NumericProperty(0) + + def __init__(self, **kwargs): + super(StrategyGame, self).__init__(**kwargs) + + number_of_regions = self.map_rows * self.map_cols + for region in xrange(0, number_of_regions): + row = region / self.map_cols + col = region % self.map_cols + self.main_map.add_widget(button.Button(text='({}, {})'.format(row, col))) class StrategyGameApp(App): diff --git a/strategygame.kv b/strategygame.kv index 8fd52a0..952799c 100644 --- a/strategygame.kv +++ b/strategygame.kv @@ -2,12 +2,16 @@ #:include debug.kv : + id: _game main_map: _main_map + map_rows: 10 + map_cols: 10 BoxLayout: orientation: 'horizontal' GridLayout: id: _main_map - cols: 10 + game: _game + cols: root.map_cols size_hint: .75, 1 BoxLayout: orientation: 'vertical' From 5decaf284d5f5a3e0c5d382ab41df6ca6b573b84 Mon Sep 17 00:00:00 2001 From: Dorian Pula Date: Sat, 4 Jun 2016 12:35:33 -0700 Subject: [PATCH 04/19] Breakout map regions into standalone widget. --- main.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/main.py b/main.py index ab87f7a..8497db0 100644 --- a/main.py +++ b/main.py @@ -1,9 +1,14 @@ +import collections + from kivy.app import App from kivy import properties from kivy.uix import button from kivy.uix.floatlayout import FloatLayout +MapCoords = collections.namedtuple('MapCoords', ['row', 'col']) + + class StrategyGame(FloatLayout): main_map = properties.ObjectProperty(None) map_rows = properties.NumericProperty(0) @@ -16,7 +21,14 @@ class StrategyGame(FloatLayout): for region in xrange(0, number_of_regions): row = region / self.map_cols col = region % self.map_cols - self.main_map.add_widget(button.Button(text='({}, {})'.format(row, col))) + self.main_map.add_widget(MapRegion(row=row, col=col)) + + +class MapRegion(button.Button): + def __init__(self, row=0, col=0, **kwargs): + self.region_in_map = MapCoords(row, col) + super(MapRegion, self).__init__(**kwargs) + self.text = '({}, {})'.format(self.region_in_map.row, self.region_in_map.col) class StrategyGameApp(App): From 5d6f3960bb7c70b5eeba6e728b6503ed58d6a76e Mon Sep 17 00:00:00 2001 From: Dorian Pula Date: Sat, 4 Jun 2016 12:51:50 -0700 Subject: [PATCH 05/19] Create logic to draw out squares. --- main.py | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/main.py b/main.py index 8497db0..6519e81 100644 --- a/main.py +++ b/main.py @@ -2,7 +2,7 @@ import collections from kivy.app import App from kivy import properties -from kivy.uix import button +from kivy.uix import button, label from kivy.uix.floatlayout import FloatLayout @@ -21,15 +21,39 @@ class StrategyGame(FloatLayout): for region in xrange(0, number_of_regions): row = region / self.map_cols col = region % self.map_cols - self.main_map.add_widget(MapRegion(row=row, col=col)) + self.main_map.add_widget(HexMapMiniRegion(row=row, col=col)) -class MapRegion(button.Button): +class HexMapMiniRegion(label.Label): def __init__(self, row=0, col=0, **kwargs): self.region_in_map = MapCoords(row, col) - super(MapRegion, self).__init__(**kwargs) - self.text = '({}, {})'.format(self.region_in_map.row, self.region_in_map.col) + super(HexMapMiniRegion, self).__init__(**kwargs) + self.draw_hex_edge() + def draw_hex_edge(self): + edge = '' + if self.region_in_map.col % 2 == 0: + row_mod = self.region_in_map.row % 6 + if row_mod == 0: + edge = ' / ' + elif row_mod in (1, 2): + edge = ' | ' + elif row_mod == 3: + edge = ' \ ' + elif row_mod in (4, 5): + edge = ' | ' + else: + row_mod = self.region_in_map.row % 6 + if row_mod == 0: + edge = ' \ ' + elif row_mod in (1, 2): + edge = ' | ' + elif row_mod == 3: + edge = ' / ' + elif row_mod in (4, 5): + edge = ' | ' + + self.text = edge class StrategyGameApp(App): def build(self): From 2e6bbd36ed63e6d61c53f0ee87cd0501f1a06cf7 Mon Sep 17 00:00:00 2001 From: Dorian Pula Date: Sat, 4 Jun 2016 12:54:21 -0700 Subject: [PATCH 06/19] Add in better naming for line edges. --- main.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/main.py b/main.py index 6519e81..54ab55e 100644 --- a/main.py +++ b/main.py @@ -2,7 +2,7 @@ import collections from kivy.app import App from kivy import properties -from kivy.uix import button, label +from kivy.uix import label from kivy.uix.floatlayout import FloatLayout @@ -35,23 +35,23 @@ class HexMapMiniRegion(label.Label): if self.region_in_map.col % 2 == 0: row_mod = self.region_in_map.row % 6 if row_mod == 0: - edge = ' / ' + edge = 'BU' elif row_mod in (1, 2): - edge = ' | ' + edge = 'L ' elif row_mod == 3: - edge = ' \ ' + edge = 'TD' elif row_mod in (4, 5): - edge = ' | ' + edge = ' R' else: row_mod = self.region_in_map.row % 6 if row_mod == 0: - edge = ' \ ' + edge = 'TD' elif row_mod in (1, 2): - edge = ' | ' + edge = ' R' elif row_mod == 3: - edge = ' / ' + edge = 'BU' elif row_mod in (4, 5): - edge = ' | ' + edge = 'L ' self.text = edge From 9cc0f805c8b84002c9443bbc117ced9c0acfc9f2 Mon Sep 17 00:00:00 2001 From: Dorian Pula Date: Sat, 4 Jun 2016 13:02:02 -0700 Subject: [PATCH 07/19] Setup initial line drawing. --- main.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/main.py b/main.py index 54ab55e..2c44d45 100644 --- a/main.py +++ b/main.py @@ -2,6 +2,7 @@ import collections from kivy.app import App from kivy import properties +from kivy import graphics from kivy.uix import label from kivy.uix.floatlayout import FloatLayout @@ -21,13 +22,13 @@ class StrategyGame(FloatLayout): for region in xrange(0, number_of_regions): row = region / self.map_cols col = region % self.map_cols - self.main_map.add_widget(HexMapMiniRegion(row=row, col=col)) + self.main_map.add_widget(HexMapCell(row=row, col=col)) -class HexMapMiniRegion(label.Label): +class HexMapCell(label.Label): def __init__(self, row=0, col=0, **kwargs): self.region_in_map = MapCoords(row, col) - super(HexMapMiniRegion, self).__init__(**kwargs) + super(HexMapCell, self).__init__(**kwargs) self.draw_hex_edge() def draw_hex_edge(self): @@ -36,6 +37,9 @@ class HexMapMiniRegion(label.Label): row_mod = self.region_in_map.row % 6 if row_mod == 0: edge = 'BU' + with self.canvas: + graphics.Color(1, 1, 1, 1) + graphics.Line(points=[self.x, self.y, self.width + self.x, self.height + self.y]) elif row_mod in (1, 2): edge = 'L ' elif row_mod == 3: From dbc704226a34eafbd9afd02f56dbd7a50c9a8bce Mon Sep 17 00:00:00 2001 From: Kjell Wooding Date: Sat, 4 Jun 2016 14:41:13 -0700 Subject: [PATCH 08/19] Draw the hex grid --- main.py | 61 ++++++++++++++++++++++++++----------------------- strategygame.kv | 29 +++++++++++++++++++++++ 2 files changed, 61 insertions(+), 29 deletions(-) diff --git a/main.py b/main.py index 2c44d45..99585fa 100644 --- a/main.py +++ b/main.py @@ -5,7 +5,7 @@ from kivy import properties from kivy import graphics from kivy.uix import label from kivy.uix.floatlayout import FloatLayout - +import math MapCoords = collections.namedtuple('MapCoords', ['row', 'col']) @@ -22,42 +22,45 @@ class StrategyGame(FloatLayout): for region in xrange(0, number_of_regions): row = region / self.map_cols col = region % self.map_cols - self.main_map.add_widget(HexMapCell(row=row, col=col)) + self.main_map.add_widget(self.pick_hex_cell(row=row, col=col)) + + + def pick_hex_cell(self, row, col): + row_mod = row % 6 + if col % 2 == 0: + if row_mod == 0: + return BU() + elif row_mod in (1, 2): + return L() + elif row_mod == 3: + return TD() + elif row_mod in (4, 5): + return R() + else: + if row_mod == 0: + return TD() + elif row_mod in (1, 2): + return R() + elif row_mod == 3: + return BU() + elif row_mod in (4, 5): + return L() class HexMapCell(label.Label): def __init__(self, row=0, col=0, **kwargs): self.region_in_map = MapCoords(row, col) super(HexMapCell, self).__init__(**kwargs) - self.draw_hex_edge() - def draw_hex_edge(self): - edge = '' - if self.region_in_map.col % 2 == 0: - row_mod = self.region_in_map.row % 6 - if row_mod == 0: - edge = 'BU' - with self.canvas: - graphics.Color(1, 1, 1, 1) - graphics.Line(points=[self.x, self.y, self.width + self.x, self.height + self.y]) - elif row_mod in (1, 2): - edge = 'L ' - elif row_mod == 3: - edge = 'TD' - elif row_mod in (4, 5): - edge = ' R' - else: - row_mod = self.region_in_map.row % 6 - if row_mod == 0: - edge = 'TD' - elif row_mod in (1, 2): - edge = ' R' - elif row_mod == 3: - edge = 'BU' - elif row_mod in (4, 5): - edge = 'L ' +class BU(HexMapCell): + pass +class TD(HexMapCell): + pass +class L(HexMapCell): + pass +class R(HexMapCell): + pass - self.text = edge class StrategyGameApp(App): def build(self): diff --git a/strategygame.kv b/strategygame.kv index 952799c..728eebc 100644 --- a/strategygame.kv +++ b/strategygame.kv @@ -22,3 +22,32 @@ DebugLabel: text: 'mini-map' size_hint: 1, .33 + +: + canvas: + Color: + rgba: (1,1,1,1) + Line: + points: (self.x, self.y, self.right, self.top) + width: 2 +: + canvas: + Color: + rgba: (1,1,1,1) + Line: + points: (self.x, self.top, self.right, self.y) + width: 2 +: + canvas: + Color: + rgba: (1,1,1,1) + Line: + points: (self.x, self.y, self.x, self.top) + width: 2 +: + canvas: + Color: + rgba: (1,1,1,1) + Line: + points: (self.right, self.y, self.right, self.top) + width: 2 From 7536075103f029a84ff4ed8acae97f8c84203de9 Mon Sep 17 00:00:00 2001 From: Kjell Wooding Date: Sat, 4 Jun 2016 14:42:55 -0700 Subject: [PATCH 09/19] add notes --- Making a Wargame.ipynb | 94 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 Making a Wargame.ipynb diff --git a/Making a Wargame.ipynb b/Making a Wargame.ipynb new file mode 100644 index 0000000..b8b26bb --- /dev/null +++ b/Making a Wargame.ipynb @@ -0,0 +1,94 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We want to make a turn-based strategy game, based on a **hexagonal grid**.\n", + "\n", + "Wait, how do we even lay out a hexagonal grid in kivy?\n", + "\n", + " http://playtechs.blogspot.com/2007/04/hex-grids.html\n", + " \n", + " Also\n", + " \n", + " http://gamedev.stackexchange.com/questions/15881/hexagonal-grid-tiles-tutorials\n", + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ignore device orientation." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's lay out a grid. First we need to draw hexagons. Clone gamecamp. change the object names.\n", + "Can we lay out the basic screen?" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "ename": "ValueError", + "evalue": "'strategygame.kv' was not found in history, as a file, url, nor in the user namespace.", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mget_ipython\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmagic\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mu'load strategygame.kv'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m/Users/kjell/anaconda/envs/py27/lib/python2.7/site-packages/IPython/core/interactiveshell.pyc\u001b[0m in \u001b[0;36mmagic\u001b[0;34m(self, arg_s)\u001b[0m\n\u001b[1;32m 2161\u001b[0m \u001b[0mmagic_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmagic_arg_s\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0marg_s\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpartition\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m' '\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2162\u001b[0m \u001b[0mmagic_name\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmagic_name\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlstrip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mprefilter\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mESC_MAGIC\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2163\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun_line_magic\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmagic_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmagic_arg_s\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2164\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2165\u001b[0m \u001b[0;31m#-------------------------------------------------------------------------\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/Users/kjell/anaconda/envs/py27/lib/python2.7/site-packages/IPython/core/interactiveshell.pyc\u001b[0m in \u001b[0;36mrun_line_magic\u001b[0;34m(self, magic_name, line)\u001b[0m\n\u001b[1;32m 2082\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'local_ns'\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msys\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_getframe\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstack_depth\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mf_locals\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2083\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbuiltin_trap\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2084\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2085\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2086\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36mload\u001b[0;34m(self, arg_s)\u001b[0m\n", + "\u001b[0;32m/Users/kjell/anaconda/envs/py27/lib/python2.7/site-packages/IPython/core/magic.pyc\u001b[0m in \u001b[0;36m\u001b[0;34m(f, *a, **k)\u001b[0m\n\u001b[1;32m 191\u001b[0m \u001b[0;31m# but it's overkill for just that one bit of state.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 192\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mmagic_deco\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 193\u001b[0;31m \u001b[0mcall\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mlambda\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 194\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 195\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mcallable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/Users/kjell/anaconda/envs/py27/lib/python2.7/site-packages/IPython/core/magics/code.pyc\u001b[0m in \u001b[0;36mload\u001b[0;34m(self, arg_s)\u001b[0m\n\u001b[1;32m 316\u001b[0m \u001b[0msearch_ns\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'n'\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mopts\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 317\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 318\u001b[0;31m \u001b[0mcontents\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshell\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfind_user_code\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msearch_ns\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0msearch_ns\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 319\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 320\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;34m's'\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mopts\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/Users/kjell/anaconda/envs/py27/lib/python2.7/site-packages/IPython/core/interactiveshell.pyc\u001b[0m in \u001b[0;36mfind_user_code\u001b[0;34m(self, target, raw, py_only, skip_encoding_cookie, search_ns)\u001b[0m\n\u001b[1;32m 3184\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mException\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3185\u001b[0m raise ValueError((\"'%s' was not found in history, as a file, url, \"\n\u001b[0;32m-> 3186\u001b[0;31m \"nor in the user namespace.\") % target)\n\u001b[0m\u001b[1;32m 3187\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3188\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcodeobj\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstring_types\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mValueError\u001b[0m: 'strategygame.kv' was not found in history, as a file, url, nor in the user namespace." + ] + } + ], + "source": [ + "%load strategygame.kv" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.11" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} From 248c6ece0c60809f353bf06e791a9edbe4a89c43 Mon Sep 17 00:00:00 2001 From: Kjell Wooding Date: Sat, 4 Jun 2016 14:49:11 -0700 Subject: [PATCH 10/19] latest notes --- Making a Wargame.ipynb | 535 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 520 insertions(+), 15 deletions(-) diff --git a/Making a Wargame.ipynb b/Making a Wargame.ipynb index b8b26bb..22a7359 100644 --- a/Making a Wargame.ipynb +++ b/Making a Wargame.ipynb @@ -39,25 +39,530 @@ }, "outputs": [ { - "ename": "ValueError", - "evalue": "'strategygame.kv' was not found in history, as a file, url, nor in the user namespace.", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mget_ipython\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmagic\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mu'load strategygame.kv'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m/Users/kjell/anaconda/envs/py27/lib/python2.7/site-packages/IPython/core/interactiveshell.pyc\u001b[0m in \u001b[0;36mmagic\u001b[0;34m(self, arg_s)\u001b[0m\n\u001b[1;32m 2161\u001b[0m \u001b[0mmagic_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmagic_arg_s\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0marg_s\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpartition\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m' '\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2162\u001b[0m \u001b[0mmagic_name\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmagic_name\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlstrip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mprefilter\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mESC_MAGIC\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2163\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun_line_magic\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmagic_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmagic_arg_s\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2164\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2165\u001b[0m \u001b[0;31m#-------------------------------------------------------------------------\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/Users/kjell/anaconda/envs/py27/lib/python2.7/site-packages/IPython/core/interactiveshell.pyc\u001b[0m in \u001b[0;36mrun_line_magic\u001b[0;34m(self, magic_name, line)\u001b[0m\n\u001b[1;32m 2082\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'local_ns'\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msys\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_getframe\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstack_depth\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mf_locals\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2083\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbuiltin_trap\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2084\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2085\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2086\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m\u001b[0m in \u001b[0;36mload\u001b[0;34m(self, arg_s)\u001b[0m\n", - "\u001b[0;32m/Users/kjell/anaconda/envs/py27/lib/python2.7/site-packages/IPython/core/magic.pyc\u001b[0m in \u001b[0;36m\u001b[0;34m(f, *a, **k)\u001b[0m\n\u001b[1;32m 191\u001b[0m \u001b[0;31m# but it's overkill for just that one bit of state.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 192\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mmagic_deco\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 193\u001b[0;31m \u001b[0mcall\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mlambda\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 194\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 195\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mcallable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/Users/kjell/anaconda/envs/py27/lib/python2.7/site-packages/IPython/core/magics/code.pyc\u001b[0m in \u001b[0;36mload\u001b[0;34m(self, arg_s)\u001b[0m\n\u001b[1;32m 316\u001b[0m \u001b[0msearch_ns\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'n'\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mopts\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 317\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 318\u001b[0;31m \u001b[0mcontents\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshell\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfind_user_code\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msearch_ns\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0msearch_ns\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 319\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 320\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;34m's'\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mopts\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/Users/kjell/anaconda/envs/py27/lib/python2.7/site-packages/IPython/core/interactiveshell.pyc\u001b[0m in \u001b[0;36mfind_user_code\u001b[0;34m(self, target, raw, py_only, skip_encoding_cookie, search_ns)\u001b[0m\n\u001b[1;32m 3184\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mException\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3185\u001b[0m raise ValueError((\"'%s' was not found in history, as a file, url, \"\n\u001b[0;32m-> 3186\u001b[0;31m \"nor in the user namespace.\") % target)\n\u001b[0m\u001b[1;32m 3187\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3188\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcodeobj\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstring_types\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mValueError\u001b[0m: 'strategygame.kv' was not found in history, as a file, url, nor in the user namespace." + "name": "stdout", + "output_type": "stream", + "text": [ + "Overwriting strategygame.kv\n" ] } ], "source": [ - "%load strategygame.kv" + "%%file strategygame.kv\n", + "\n", + "#:include debug.kv\n", + "\n", + ":\n", + " BoxLayout:\n", + " orientation: 'horizontal'\n", + " DebugLabel:\n", + " text: 'Main map'\n", + " size_hint: .75, 1\n", + " BoxLayout:\n", + " orientation: 'vertical'\n", + " size_hint: .25, 1\n", + " DebugLabel:\n", + " text: 'status'\n", + " size_hint: 1, .66\n", + " DebugLabel:\n", + " text: 'mini-map'\n", + " size_hint: 1, .33\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Overwriting main.py\n" + ] + } + ], + "source": [ + "%%file main.py\n", + "from kivy.app import App\n", + "from kivy.uix.floatlayout import FloatLayout\n", + "\n", + "\n", + "class StrategyGame(FloatLayout):\n", + " pass\n", + "\n", + "\n", + "class StrategyGameApp(App):\n", + " def build(self):\n", + " return StrategyGame()\n", + "\n", + "if __name__ == '__main__':\n", + " StrategyGameApp().run()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "#!python main.py\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's make a gridlayout in the game area, and give it a label so we can refer to it from our code. We are going to build a rectangular grid" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "%%file strategygame.kv\n", + "\n", + "#:include debug.kv\n", + "\n", + ":\n", + " main_map: _main_map\n", + " BoxLayout:\n", + " orientation: 'horizontal'\n", + " GridLayout:\n", + " id: _main_map\n", + " cols: 10\n", + " size_hint: .75, 1\n", + " BoxLayout:\n", + " orientation: 'vertical'\n", + " size_hint: .25, 1\n", + " DebugLabel:\n", + " text: 'status'\n", + " size_hint: 1, .66\n", + " DebugLabel:\n", + " text: 'mini-map'\n", + " size_hint: 1, .33\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's hook to that from code. We will do this in `__init__` in our main StrategyGame class. Let's make a loop to add buttons to the root widget. We will use properties in the kv file to determine how many rows/cols to add. We will also need to refer to various objects in the widget hierarchy in the code." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can refer to the top-level object (non-indented) as `root` in the kv file, but it we want to refer to conveniently elsewhere in the code, we need to use an id.\n", + "\n", + "`id: _game`\n", + "\n", + "and then from any widget we want to refer to it, we do a \n", + "\n", + "`game: _game`\n", + "\n", + "We'll use this to access the number of regions to layout in the grid via `map_cols` and `map_rows` from the main game widget. \n", + "\n", + "Fill in grids: it fills it in by default, left to right, top to bottom, and give them coordinate references. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "%%file strategygame.kv\n", + "\n", + "#:include debug.kv\n", + "\n", + ":\n", + " id: _game\n", + " main_map: _main_map\n", + " map_rows: 10\n", + " map_cols: 10\n", + " BoxLayout:\n", + " orientation: 'horizontal'\n", + " GridLayout:\n", + " id: _main_map\n", + " game: _game\n", + " cols: root.map_cols\n", + " size_hint: .75, 1\n", + " BoxLayout:\n", + " orientation: 'vertical'\n", + " size_hint: .25, 1\n", + " DebugLabel:\n", + " text: 'status'\n", + " size_hint: 1, .66\n", + " DebugLabel:\n", + " text: 'mini-map'\n", + " size_hint: 1, .33\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# %load main.py\n", + "from kivy.app import App\n", + "from kivy import properties\n", + "from kivy.uix import button\n", + "from kivy.uix.floatlayout import FloatLayout\n", + "\n", + "\n", + "class StrategyGame(FloatLayout):\n", + " main_map = properties.ObjectProperty(None)\n", + " map_rows = properties.NumericProperty(0)\n", + " map_cols = properties.NumericProperty(0)\n", + "\n", + " def __init__(self, **kwargs):\n", + " super(StrategyGame, self).__init__(**kwargs)\n", + "\n", + " number_of_regions = self.map_rows * self.map_cols\n", + " for region in xrange(0, number_of_regions):\n", + " row = region / self.map_cols\n", + " col = region % self.map_cols\n", + " self.main_map.add_widget(button.Button(text='({}, {})'.format(row, col)))\n", + "\n", + "\n", + "class StrategyGameApp(App):\n", + " def build(self):\n", + " return StrategyGame()\n", + "\n", + "if __name__ == '__main__':\n", + " StrategyGameApp().run()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We draw alternating rows with the patterns:\n", + "```\n", + "/ \\\n", + "| |\n", + "| |\n", + "```\n", + "and\n", + "```\n", + "\\ /\n", + " |\n", + " |\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "%%file strategygame.kv\n", + "\n", + "#:include debug.kv\n", + "\n", + ":\n", + " id: _game\n", + " main_map: _main_map\n", + " map_rows: 10\n", + " map_cols: 10\n", + " BoxLayout:\n", + " orientation: 'horizontal'\n", + " GridLayout:\n", + " id: _main_map\n", + " game: _game\n", + " cols: root.map_cols\n", + " size_hint: .75, 1\n", + " BoxLayout:\n", + " orientation: 'vertical'\n", + " size_hint: .25, 1\n", + " DebugLabel:\n", + " text: 'status'\n", + " size_hint: 1, .66\n", + " DebugLabel:\n", + " text: 'mini-map'\n", + " size_hint: 1, .33\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "%%file main.py\n", + "from kivy.app import App\n", + "from kivy import properties\n", + "from kivy.uix import button\n", + "from kivy.uix.floatlayout import FloatLayout\n", + "\n", + "\n", + "class StrategyGame(FloatLayout):\n", + " main_map = properties.ObjectProperty(None)\n", + " map_rows = properties.NumericProperty(0)\n", + " map_cols = properties.NumericProperty(0)\n", + "\n", + " def __init__(self, **kwargs):\n", + " super(StrategyGame, self).__init__(**kwargs)\n", + "\n", + " number_of_regions = self.map_rows * self.map_cols\n", + " for region in xrange(0, number_of_regions):\n", + " row = region / self.map_cols\n", + " col = region % self.map_cols\n", + " self.main_map.add_widget(button.Button(text='({}, {})'.format(row, col)))\n", + "\n", + "\n", + "class StrategyGameApp(App):\n", + " def build(self):\n", + " return StrategyGame()\n", + "\n", + "if __name__ == '__main__':\n", + " StrategyGameApp().run()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Wait, that doesn't draw where we think it should.'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "%%file main.py\n", + "import collections\n", + "\n", + "from kivy.app import App\n", + "from kivy import properties\n", + "from kivy import graphics\n", + "from kivy.uix import label\n", + "from kivy.uix.floatlayout import FloatLayout\n", + "\n", + "\n", + "MapCoords = collections.namedtuple('MapCoords', ['row', 'col'])\n", + "\n", + "\n", + "class StrategyGame(FloatLayout):\n", + " main_map = properties.ObjectProperty(None)\n", + " map_rows = properties.NumericProperty(0)\n", + " map_cols = properties.NumericProperty(0)\n", + "\n", + " def __init__(self, **kwargs):\n", + " super(StrategyGame, self).__init__(**kwargs)\n", + "\n", + " number_of_regions = self.map_rows * self.map_cols\n", + " for region in xrange(0, number_of_regions):\n", + " row = region / self.map_cols\n", + " col = region % self.map_cols\n", + " self.main_map.add_widget(HexMapCell(row=row, col=col))\n", + "\n", + "\n", + "class HexMapCell(label.Label):\n", + " def __init__(self, row=0, col=0, **kwargs):\n", + " self.region_in_map = MapCoords(row, col)\n", + " super(HexMapCell, self).__init__(**kwargs)\n", + " self.draw_hex_edge()\n", + "\n", + " def draw_hex_edge(self):\n", + " edge = ''\n", + " if self.region_in_map.col % 2 == 0:\n", + " row_mod = self.region_in_map.row % 6\n", + " if row_mod == 0:\n", + " edge = 'BU'\n", + " with self.canvas:\n", + " graphics.Color(1, 1, 1, 1)\n", + " graphics.Line(points=[self.x, self.y, self.width + self.x, self.height + self.y])\n", + " elif row_mod in (1, 2):\n", + " edge = 'L '\n", + " elif row_mod == 3:\n", + " edge = 'TD'\n", + " elif row_mod in (4, 5):\n", + " edge = ' R'\n", + " else:\n", + " row_mod = self.region_in_map.row % 6\n", + " if row_mod == 0:\n", + " edge = 'TD'\n", + " elif row_mod in (1, 2):\n", + " edge = ' R'\n", + " elif row_mod == 3:\n", + " edge = 'BU'\n", + " elif row_mod in (4, 5):\n", + " edge = 'L '\n", + "\n", + " self.text = edge\n", + "\n", + "class StrategyGameApp(App):\n", + " def build(self):\n", + " return StrategyGame()\n", + "\n", + "if __name__ == '__main__':\n", + " StrategyGameApp().run()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Overwriting main.py\n" + ] + } + ], + "source": [ + "%%file main.py\n", + "from kivy.app import App\n", + "from kivy.uix.gridlayout import GridLayout\n", + "from kivy.lang import Builder\n", + "from kivy.properties import NumericProperty\n", + "\n", + "class HelloWorld(GridLayout):\n", + " cols = NumericProperty(4)\n", + " def __init__(self, **kw):\n", + " super(HelloWorld, self).__init__(**kw)\n", + " self.add_widget(self.BU())\n", + " self.add_widget(self.TD())\n", + " self.add_widget(self.BU())\n", + " self.add_widget(self.TD())\n", + "\n", + " def BU(self):\n", + " return Builder.load_string('''\n", + "Label:\n", + " canvas:\n", + " Color:\n", + " rgba: (1,1,1,1)\n", + " Line:\n", + " points: (self.x, self.y, self.right, self.top)\n", + " width: 2''')\n", + "\n", + " def TD(self):\n", + " return Builder.load_string('''\n", + "Label:\n", + " canvas:\n", + " Color:\n", + " rgba: (1,1,1,1)\n", + " Line:\n", + " points: (self.x, self.top, self.right, self.y)\n", + " width: 2''')\n", + "\n", + " def L(self):\n", + " return Builder.load_string('''\n", + "Label:\n", + " canvas:\n", + " Color:\n", + " rgba: (1,1,1,1)\n", + " Line:\n", + " points: (self.x, self.y, self.x, self.top)\n", + " width: 2''')\n", + "\n", + " def R(self):\n", + " return Builder.load_string('''\n", + "Label:\n", + " canvas:\n", + " Color:\n", + " rgba: (1,1,1,1)\n", + " Line:\n", + " points: (self.right, self.y, self.right, self.top)\n", + " width: 2''')\n", + "\n", + "\n", + "class HelloWorldApp(App):\n", + " def build(self):\n", + " return HelloWorld()\n", + "\n", + "if __name__ == '__main__':\n", + " HelloWorldApp().run()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# %load strategygame.kv\n", + "\n", + "#:include debug.kv\n", + "\n", + ":\n", + " id: _game\n", + " main_map: _main_map\n", + " map_rows: 10\n", + " map_cols: 10\n", + " BoxLayout:\n", + " orientation: 'horizontal'\n", + " GridLayout:\n", + " id: _main_map\n", + " game: _game\n", + " cols: root.map_cols\n", + " size_hint: .75, 1\n", + " BoxLayout:\n", + " orientation: 'vertical'\n", + " size_hint: .25, 1\n", + " DebugLabel:\n", + " text: 'status'\n", + " size_hint: 1, .66\n", + " DebugLabel:\n", + " text: 'mini-map'\n", + " size_hint: 1, .33\n" ] }, { From 3d77ab264b3ba548248db0ba65f262f214be6d87 Mon Sep 17 00:00:00 2001 From: Kjell Wooding Date: Sat, 4 Jun 2016 14:55:11 -0700 Subject: [PATCH 11/19] first try at fixing the aspect ratio --- main.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/main.py b/main.py index 99585fa..ab6737b 100644 --- a/main.py +++ b/main.py @@ -51,6 +51,9 @@ class HexMapCell(label.Label): def __init__(self, row=0, col=0, **kwargs): self.region_in_map = MapCoords(row, col) super(HexMapCell, self).__init__(**kwargs) + self.size_hint = (1,None) + self.height = self.width / math.sqrt(3) + class BU(HexMapCell): pass From cc1604fe36687c46c84e28e9ed804f5c18f3647d Mon Sep 17 00:00:00 2001 From: Kjell Wooding Date: Sat, 4 Jun 2016 15:08:18 -0700 Subject: [PATCH 12/19] fix aspect ratio of hex grid --- Making a Wargame.ipynb | 9 +++++++++ main.py | 4 +--- strategygame.kv | 9 +++++++-- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/Making a Wargame.ipynb b/Making a Wargame.ipynb index 22a7359..849d20e 100644 --- a/Making a Wargame.ipynb +++ b/Making a Wargame.ipynb @@ -565,6 +565,15 @@ " size_hint: 1, .33\n" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": null, diff --git a/main.py b/main.py index ab6737b..31d0ac5 100644 --- a/main.py +++ b/main.py @@ -48,12 +48,10 @@ class StrategyGame(FloatLayout): class HexMapCell(label.Label): + def __init__(self, row=0, col=0, **kwargs): self.region_in_map = MapCoords(row, col) super(HexMapCell, self).__init__(**kwargs) - self.size_hint = (1,None) - self.height = self.width / math.sqrt(3) - class BU(HexMapCell): pass diff --git a/strategygame.kv b/strategygame.kv index 728eebc..e7b7481 100644 --- a/strategygame.kv +++ b/strategygame.kv @@ -1,10 +1,10 @@ - +#:import math math #:include debug.kv : id: _game main_map: _main_map - map_rows: 10 + map_rows: 30 map_cols: 10 BoxLayout: orientation: 'horizontal' @@ -23,6 +23,7 @@ text: 'mini-map' size_hint: 1, .33 + : canvas: Color: @@ -51,3 +52,7 @@ Line: points: (self.right, self.y, self.right, self.top) width: 2 + +: + size_hint: 1, None + height: self.width / math.sqrt(3) From 4bde100b4c3ae01b59f8490111ef957a9779badc Mon Sep 17 00:00:00 2001 From: Amy Wooding Date: Sat, 4 Jun 2016 15:10:18 -0700 Subject: [PATCH 13/19] drawing hexagons! --- Making a Wargame.ipynb | 209 +++++++++++++++++++++++++++++++++++------ 1 file changed, 178 insertions(+), 31 deletions(-) diff --git a/Making a Wargame.ipynb b/Making a Wargame.ipynb index 22a7359..dd0793b 100644 --- a/Making a Wargame.ipynb +++ b/Making a Wargame.ipynb @@ -33,19 +33,11 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Overwriting strategygame.kv\n" - ] - } - ], + "outputs": [], "source": [ "%%file strategygame.kv\n", "\n", @@ -70,19 +62,11 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Overwriting main.py\n" - ] - } - ], + "outputs": [], "source": [ "%%file main.py\n", "from kivy.app import App\n", @@ -112,7 +96,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": { "collapsed": false }, @@ -452,19 +436,11 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Overwriting main.py\n" - ] - } - ], + "outputs": [], "source": [ "%%file main.py\n", "from kivy.app import App\n", @@ -565,6 +541,177 @@ " size_hint: 1, .33\n" ] }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "## Trying to draw the hexmap\n", + "\n", + "We tried adding the ability to style our widgets for to draw the Hexmap using lines like this\n", + "\n", + " BU: /\n", + " TD: \\\n", + " L: |\n", + " R: |\n", + "We get hexs now, but we need to figure out how to do the aspect ratio properly now...for a spiky top, we need each grid widget to have aspec ratio $$\\sqrt{3}\\cdot height = width$$" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "%%file strategygame.kv\n", + "\n", + "#:include debug.kv\n", + "\n", + ":\n", + " id: _game\n", + " main_map: _main_map\n", + " map_rows: 10\n", + " map_cols: 10\n", + " BoxLayout:\n", + " orientation: 'horizontal'\n", + " GridLayout:\n", + " id: _main_map\n", + " game: _game\n", + " cols: root.map_cols\n", + " size_hint: .75, 1\n", + " BoxLayout:\n", + " orientation: 'vertical'\n", + " size_hint: .25, 1\n", + " DebugLabel:\n", + " text: 'status'\n", + " size_hint: 1, .66\n", + " DebugLabel:\n", + " text: 'mini-map'\n", + " size_hint: 1, .33\n", + "\n", + ":\n", + " canvas:\n", + " Color:\n", + " rgba: (1,1,1,1)\n", + " Line:\n", + " points: (self.x, self.y, self.right, self.top)\n", + " width: 2\n", + ":\n", + " canvas:\n", + " Color:\n", + " rgba: (1,1,1,1)\n", + " Line:\n", + " points: (self.x, self.top, self.right, self.y)\n", + " width: 2\n", + ":\n", + " canvas:\n", + " Color:\n", + " rgba: (1,1,1,1)\n", + " Line:\n", + " points: (self.x, self.y, self.x, self.top)\n", + " width: 2\n", + ":\n", + " canvas:\n", + " Color:\n", + " rgba: (1,1,1,1)\n", + " Line:\n", + " points: (self.right, self.y, self.right, self.top)\n", + " width: 2\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%%file main.py\n", + "import collections\n", + "\n", + "from kivy.app import App\n", + "from kivy import properties\n", + "from kivy import graphics\n", + "from kivy.uix import label\n", + "from kivy.uix.floatlayout import FloatLayout\n", + "import math\n", + "\n", + "MapCoords = collections.namedtuple('MapCoords', ['row', 'col'])\n", + "\n", + "\n", + "class StrategyGame(FloatLayout):\n", + " main_map = properties.ObjectProperty(None)\n", + " map_rows = properties.NumericProperty(0)\n", + " map_cols = properties.NumericProperty(0)\n", + "\n", + " def __init__(self, **kwargs):\n", + " super(StrategyGame, self).__init__(**kwargs)\n", + "\n", + " number_of_regions = self.map_rows * self.map_cols\n", + " for region in xrange(0, number_of_regions):\n", + " row = region / self.map_cols\n", + " col = region % self.map_cols\n", + " self.main_map.add_widget(self.pick_hex_cell(row=row, col=col))\n", + "\n", + "\n", + " def pick_hex_cell(self, row, col):\n", + " row_mod = row % 6\n", + " if col % 2 == 0:\n", + " if row_mod == 0:\n", + " return BU()\n", + " elif row_mod in (1, 2):\n", + " return L()\n", + " elif row_mod == 3:\n", + " return TD()\n", + " elif row_mod in (4, 5):\n", + " return R()\n", + " else:\n", + " if row_mod == 0:\n", + " return TD()\n", + " elif row_mod in (1, 2):\n", + " return R()\n", + " elif row_mod == 3:\n", + " return BU()\n", + " elif row_mod in (4, 5):\n", + " return L()\n", + "\n", + "\n", + "class HexMapCell(label.Label):\n", + " def __init__(self, row=0, col=0, **kwargs):\n", + " self.region_in_map = MapCoords(row, col)\n", + " super(HexMapCell, self).__init__(**kwargs)\n", + "\n", + "class BU(HexMapCell):\n", + " pass\n", + "class TD(HexMapCell):\n", + " pass\n", + "class L(HexMapCell):\n", + " pass\n", + "class R(HexMapCell):\n", + " pass\n", + "\n", + "\n", + "class StrategyGameApp(App):\n", + " def build(self):\n", + " return StrategyGame()\n", + "\n", + "if __name__ == '__main__':\n", + " StrategyGameApp().run()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": null, From bbf851d4672e4371ff2847b98d12dfd7215cef60 Mon Sep 17 00:00:00 2001 From: Dorian Pula Date: Sat, 4 Jun 2016 15:43:40 -0700 Subject: [PATCH 14/19] Switch to labels and added two ways to colour backgrounds. --- strategygame.kv | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/strategygame.kv b/strategygame.kv index e7b7481..7efe1d1 100644 --- a/strategygame.kv +++ b/strategygame.kv @@ -1,5 +1,4 @@ #:import math math -#:include debug.kv : id: _game @@ -16,12 +15,20 @@ BoxLayout: orientation: 'vertical' size_hint: .25, 1 - DebugLabel: + Label: + id: _stats text: 'status' size_hint: 1, .66 - DebugLabel: + canvas.before: + Color: + rgba: .49, .49, .81, 1 + Rectangle: + pos: _stats.pos + size: _stats.size + Button: text: 'mini-map' size_hint: 1, .33 + background_color: .75, .71, .99, 1 : From 7eb4b343a55881ae495c5248c8c3e2bcc5826d25 Mon Sep 17 00:00:00 2001 From: Dorian Pula Date: Sat, 4 Jun 2016 17:37:39 -0700 Subject: [PATCH 15/19] Add in way to add in a single and multiple boxes for handling control of units. --- main.py | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/main.py b/main.py index 31d0ac5..b04e194 100644 --- a/main.py +++ b/main.py @@ -1,11 +1,9 @@ import collections +import random -from kivy.app import App -from kivy import properties -from kivy import graphics -from kivy.uix import label +from kivy import app, properties +from kivy.uix import button, label from kivy.uix.floatlayout import FloatLayout -import math MapCoords = collections.namedtuple('MapCoords', ['row', 'col']) @@ -22,10 +20,18 @@ class StrategyGame(FloatLayout): for region in xrange(0, number_of_regions): row = region / self.map_cols col = region % self.map_cols - self.main_map.add_widget(self.pick_hex_cell(row=row, col=col)) + # Add hex cells to make up the map. + hex_cell = self.pick_hex_cell(row=row, col=col) + self.main_map.add_widget(hex_cell) - def pick_hex_cell(self, row, col): + # Add overlay conditionally. + # if (row % 6 == 2 and col % 2 == 0) or (row % 6 == 5 and col % 2 == 1): + if row == 2 and col == 0: + self.add_widget(HexMapControlCell(hex_bind=hex_cell)) + + @staticmethod + def pick_hex_cell(row, col): row_mod = row % 6 if col % 2 == 0: if row_mod == 0: @@ -48,10 +54,9 @@ class StrategyGame(FloatLayout): class HexMapCell(label.Label): - def __init__(self, row=0, col=0, **kwargs): - self.region_in_map = MapCoords(row, col) super(HexMapCell, self).__init__(**kwargs) + self.coords = MapCoords(row, col) class BU(HexMapCell): pass @@ -63,7 +68,26 @@ class R(HexMapCell): pass -class StrategyGameApp(App): +class HexMapControlCell(button.Button): + def __init__(self, hex_bind=None, **kwargs): + super(HexMapControlCell, self).__init__(**kwargs) + self.hex_bind = hex_bind + # self.background_color = random.random(), random.random(), random.random(), 0.1 + # self.background_color = random.random(), random.random(), random.random(), 0.25 + self.background_color = random.random(), random.random(), random.random(), 1 + self.bind(pos=self.reposition_control_cell, size=self.resize_control_cell) + + def reposition_control_cell(self, obj, value): + # import pdb + # pdb.set_trace() + self.pos = self.hex_bind.pos + + def resize_control_cell(self, obj, value): + self.height = self.hex_bind.height * 2 + self.width = self.hex_bind.width * 2 + + +class StrategyGameApp(app.App): def build(self): return StrategyGame() From 02c84566cdebe7b33f77577a257027a9db948914 Mon Sep 17 00:00:00 2001 From: Dorian Pula Date: Sat, 4 Jun 2016 17:57:52 -0700 Subject: [PATCH 16/19] Attempt to create multiple control points. --- main.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/main.py b/main.py index b04e194..f29b13c 100644 --- a/main.py +++ b/main.py @@ -26,8 +26,8 @@ class StrategyGame(FloatLayout): self.main_map.add_widget(hex_cell) # Add overlay conditionally. - # if (row % 6 == 2 and col % 2 == 0) or (row % 6 == 5 and col % 2 == 1): - if row == 2 and col == 0: + if (row % 6 == 2 and col % 2 == 0) or (row % 6 == 5 and col % 2 == 1): + print('({}, {})'.format(row, col)) self.add_widget(HexMapControlCell(hex_bind=hex_cell)) @staticmethod @@ -58,12 +58,19 @@ class HexMapCell(label.Label): super(HexMapCell, self).__init__(**kwargs) self.coords = MapCoords(row, col) + class BU(HexMapCell): pass + + class TD(HexMapCell): pass + + class L(HexMapCell): pass + + class R(HexMapCell): pass @@ -72,14 +79,11 @@ class HexMapControlCell(button.Button): def __init__(self, hex_bind=None, **kwargs): super(HexMapControlCell, self).__init__(**kwargs) self.hex_bind = hex_bind - # self.background_color = random.random(), random.random(), random.random(), 0.1 - # self.background_color = random.random(), random.random(), random.random(), 0.25 self.background_color = random.random(), random.random(), random.random(), 1 self.bind(pos=self.reposition_control_cell, size=self.resize_control_cell) + self.text = '({}, {})'.format(self.hex_bind.coords.row, self.hex_bind.coords.col) def reposition_control_cell(self, obj, value): - # import pdb - # pdb.set_trace() self.pos = self.hex_bind.pos def resize_control_cell(self, obj, value): From e3b32ca4fa8cb3f54b10aa9c309f3aa3d40c1067 Mon Sep 17 00:00:00 2001 From: Amy Wooding Date: Sat, 4 Jun 2016 21:01:21 -0700 Subject: [PATCH 17/19] up to adding an overlay --- Making a Wargame.ipynb | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/Making a Wargame.ipynb b/Making a Wargame.ipynb index 8d466e9..26a820a 100644 --- a/Making a Wargame.ipynb +++ b/Making a Wargame.ipynb @@ -704,13 +704,13 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": { "collapsed": false }, - "outputs": [], - "source": [] + "source": [ + "Replaced the debug labels and coloured the status and minimap two different ways. " + ] }, { "cell_type": "code", @@ -719,7 +719,23 @@ "collapsed": true }, "outputs": [], - "source": [] + "source": [ + "#%load strategygame.kv" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "We should probably have a viewer and a hexagon map underneath!!\n", + "\n", + "But not for now...let's make an overlay of boxes...and label them with an \"offset-r)\n", + "\n", + "Hmmmm....overlay...is...having...issues. \n", + "\n" + ] }, { "cell_type": "code", From f5aaa50433c4c26c3d9fd1252636cf662b6da79e Mon Sep 17 00:00:00 2001 From: Amy Wooding Date: Sat, 4 Jun 2016 22:20:00 -0700 Subject: [PATCH 18/19] hexagons work!! hurray! --- Making a Wargame.ipynb | 373 ++++++++++++++++++++++++++++++++++++++++- main.py | 23 ++- strategygame.kv | 39 ++--- 3 files changed, 401 insertions(+), 34 deletions(-) diff --git a/Making a Wargame.ipynb b/Making a Wargame.ipynb index 26a820a..614b7f2 100644 --- a/Making a Wargame.ipynb +++ b/Making a Wargame.ipynb @@ -720,7 +720,189 @@ }, "outputs": [], "source": [ - "#%load strategygame.kv" + "%%file strategygame.kv\n", + "#:import math math\n", + "\n", + ":\n", + " id: _game\n", + " main_map: _main_map\n", + " map_rows: 30\n", + " map_cols: 10\n", + " BoxLayout:\n", + " orientation: 'horizontal'\n", + " GridLayout:\n", + " id: _main_map\n", + " game: _game\n", + " cols: root.map_cols\n", + " size_hint: .75, 1\n", + " BoxLayout:\n", + " orientation: 'vertical'\n", + " size_hint: .25, 1\n", + " Label:\n", + " id: _stats\n", + " text: 'status'\n", + " size_hint: 1, .66\n", + " canvas.before:\n", + " Color:\n", + " rgba: .49, .49, .81, 1\n", + " Rectangle:\n", + " pos: _stats.pos\n", + " size: _stats.size\n", + " Button:\n", + " text: 'mini-map'\n", + " size_hint: 1, .33\n", + " background_color: .75, .71, .99, 1\n", + "\n", + "\n", + ":\n", + " canvas:\n", + " Color:\n", + " rgba: (1,1,1,1)\n", + " Line:\n", + " points: (self.x, self.y, self.right, self.top)\n", + " width: 2\n", + ":\n", + " canvas:\n", + " Color:\n", + " rgba: (1,1,1,1)\n", + " Line:\n", + " points: (self.x, self.top, self.right, self.y)\n", + " width: 2\n", + ":\n", + " canvas:\n", + " Color:\n", + " rgba: (1,1,1,1)\n", + " Line:\n", + " points: (self.x, self.y, self.x, self.top)\n", + " width: 2\n", + ":\n", + " canvas:\n", + " Color:\n", + " rgba: (1,1,1,1)\n", + " Line:\n", + " points: (self.right, self.y, self.right, self.top)\n", + " width: 2\n", + "\n", + ":\n", + " size_hint: 1, None\n", + " height: self.width / math.sqrt(3)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "%%file main.py\n", + "import collections\n", + "import random\n", + "\n", + "from kivy import app, properties\n", + "from kivy.uix import button, label\n", + "from kivy.uix.floatlayout import FloatLayout\n", + "\n", + "MapCoords = collections.namedtuple('MapCoords', ['row', 'col'])\n", + "\n", + "\n", + "class StrategyGame(FloatLayout):\n", + " main_map = properties.ObjectProperty(None)\n", + " map_rows = properties.NumericProperty(0)\n", + " map_cols = properties.NumericProperty(0)\n", + "\n", + " def __init__(self, **kwargs):\n", + " super(StrategyGame, self).__init__(**kwargs)\n", + "\n", + " number_of_regions = self.map_rows * self.map_cols\n", + " for region in xrange(0, number_of_regions):\n", + " row = region / self.map_cols\n", + " col = region % self.map_cols\n", + "\n", + " # Add hex cells to make up the map.\n", + " hex_cell = self.pick_hex_cell(row=row, col=col)\n", + " self.main_map.add_widget(hex_cell)\n", + "\n", + " # Add overlay conditionally.\n", + " if (row % 6 == 2 and col % 2 == 0) or (row % 6 == 5 and col % 2 == 1):\n", + " print('({}, {})'.format(row, col))\n", + " self.add_widget(HexMapControlCell(hex_bind=hex_cell))\n", + "\n", + " @staticmethod\n", + " def pick_hex_cell(row, col):\n", + " row_mod = row % 6\n", + " if col % 2 == 0:\n", + " if row_mod == 0:\n", + " return BU()\n", + " elif row_mod in (1, 2):\n", + " return L()\n", + " elif row_mod == 3:\n", + " return TD()\n", + " elif row_mod in (4, 5):\n", + " return R()\n", + " else:\n", + " if row_mod == 0:\n", + " return TD()\n", + " elif row_mod in (1, 2):\n", + " return R()\n", + " elif row_mod == 3:\n", + " return BU()\n", + " elif row_mod in (4, 5):\n", + " return L()\n", + "\n", + "\n", + "class HexMapCell(label.Label):\n", + " def __init__(self, row=0, col=0, **kwargs):\n", + " super(HexMapCell, self).__init__(**kwargs)\n", + " self.coords = MapCoords(row, col)\n", + "\n", + "\n", + "class BU(HexMapCell):\n", + " pass\n", + "\n", + "\n", + "class TD(HexMapCell):\n", + " pass\n", + "\n", + "\n", + "class L(HexMapCell):\n", + " pass\n", + "\n", + "\n", + "class R(HexMapCell):\n", + " pass\n", + "\n", + "\n", + "class HexMapControlCell(button.Button):\n", + " def __init__(self, hex_bind=None, **kwargs):\n", + " super(HexMapControlCell, self).__init__(**kwargs)\n", + " self.hex_bind = hex_bind\n", + " self.background_color = random.random(), random.random(), random.random(), 1\n", + " self.bind(pos=self.reposition_control_cell, size=self.resize_control_cell)\n", + " self.text = '({}, {})'.format(self.hex_bind.coords.row, self.hex_bind.coords.col)\n", + "\n", + " def reposition_control_cell(self, obj, value):\n", + " self.pos = self.hex_bind.pos\n", + "\n", + " def resize_control_cell(self, obj, value):\n", + " self.height = self.hex_bind.height * 2\n", + " self.width = self.hex_bind.width * 2\n", + "\n", + "\n", + "class StrategyGameApp(app.App):\n", + " def build(self):\n", + " return StrategyGame()\n", + "\n", + "if __name__ == '__main__':\n", + " StrategyGameApp().run()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Warning** if you run this your will get an error!!" ] }, { @@ -744,7 +926,194 @@ "collapsed": true }, "outputs": [], - "source": [] + "source": [ + "%%file strategygame.kv\n", + "#:import math math\n", + "#:include debug.kv\n", + "\n", + ":\n", + " id: _game\n", + " main_map: _main_map\n", + " map_rows: 30\n", + " map_cols: 10\n", + " BoxLayout:\n", + " orientation: 'horizontal'\n", + " GridLayout:\n", + " id: _main_map\n", + " game: _game\n", + " cols: root.map_cols\n", + " size_hint: .75, 1\n", + " BoxLayout:\n", + " orientation: 'vertical'\n", + " size_hint: .25, 1\n", + " Label:\n", + " id: _stats\n", + " text: 'status'\n", + " size_hint: 1, .66\n", + " canvas.before:\n", + " Color:\n", + " rgba: .49, .49, .81, 1\n", + " Rectangle:\n", + " pos: _stats.pos\n", + " size: _stats.size\n", + " Button:\n", + " text: 'mini-map'\n", + " size_hint: 1, .33\n", + " background_color: .75, .71, .99, 1\n", + "\n", + ":\n", + " pos_hint: {'center_x':.5, 'center_y':.5}\n", + " canvas.after:\n", + " Color:\n", + " rgba: 1,1,1,1\n", + " Ellipse:\n", + " segments: 6\n", + " pos: self.pos\n", + " size: min(self.width, self.height), min(self.width, self.height)\n", + "\n", + ":\n", + " size_hint: 1, None\n", + " height: self.width / math.sqrt(3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%%file main.py\n", + "import collections\n", + "import random\n", + "import math\n", + "from kivy import app, properties\n", + "from kivy.uix import button, label\n", + "from kivy.uix.floatlayout import FloatLayout\n", + "from kivy.graphics import Color, Ellipse, Line\n", + "from kivy.logger import Logger\n", + "\n", + "MapCoords = collections.namedtuple('MapCoords', ['row', 'col'])\n", + "\n", + "\n", + "class StrategyGame(FloatLayout):\n", + " main_map = properties.ObjectProperty(None)\n", + " map_rows = properties.NumericProperty(0)\n", + " map_cols = properties.NumericProperty(0)\n", + "\n", + " def __init__(self, **kwargs):\n", + " super(StrategyGame, self).__init__(**kwargs)\n", + "\n", + " number_of_regions = self.map_rows * self.map_cols\n", + " for region in xrange(0, number_of_regions):\n", + " row = region / self.map_cols\n", + " col = region % self.map_cols\n", + "\n", + " # Add hex cells to make up the map.\n", + " hex_cell = self.pick_hex_cell(row=row, col=col)\n", + " self.main_map.add_widget(hex_cell)\n", + "\n", + " # Add overlay conditionally.\n", + " if (row % 6 == 1 and col % 2 == 1) or (row % 6 == 4 and col % 2 == 0):\n", + " print('({}, {})'.format(row, col))\n", + " #radius = math.sqrt(hex_cell.width**2 + hex_cell.height**2)\n", + " radius = 2*hex_cell.height\n", + " with hex_cell.canvas.after:\n", + " Color(1,0,1,1)\n", + " hex_cell.ell = Line(circle=(hex_cell.x, hex_cell.y,radius, 0, 360, 6), width=2)\n", + " hex_cell.bind(pos=hex_cell.update_pos, size=hex_cell.update_pos)\n", + "\n", + "\n", + " @staticmethod\n", + " def pick_hex_cell(row, col):\n", + " row_mod = row % 6\n", + " if col % 2 == 0:\n", + " if row_mod == 0:\n", + " return BU()\n", + " elif row_mod in (1, 2):\n", + " return L()\n", + " elif row_mod == 3:\n", + " return TD()\n", + " elif row_mod in (4, 5):\n", + " return R()\n", + " else:\n", + " if row_mod == 0:\n", + " return TD()\n", + " elif row_mod in (1, 2):\n", + " return R()\n", + " elif row_mod == 3:\n", + " return BU()\n", + " elif row_mod in (4, 5):\n", + " return L()\n", + "\n", + "\n", + "\n", + "class HexMapCell(label.Label):\n", + " def __init__(self, row=0, col=0, **kwargs):\n", + " super(HexMapCell, self).__init__(**kwargs)\n", + " self.coords = MapCoords(row, col)\n", + "\n", + " def update_pos(self, instance, value):\n", + " Logger.info(\"StratGame: {}\".format(instance))\n", + " #radius = math.sqrt(self.width**2 + self.height**2)\n", + " radius = 2*self.height\n", + " self.ell.circle = (self.x, self.y, radius, 0, 360, 6)\n", + "\n", + "\n", + "\n", + "class BU(HexMapCell):\n", + " pass\n", + "\n", + "\n", + "class TD(HexMapCell):\n", + " pass\n", + "\n", + "\n", + "class L(HexMapCell):\n", + " pass\n", + "\n", + "\n", + "class R(HexMapCell):\n", + " pass\n", + "\n", + "\n", + "\n", + "class HexMapControlCell(button.Button):\n", + " def __init__(self, hex_bind=None, **kwargs):\n", + " super(HexMapControlCell, self).__init__(**kwargs)\n", + " self.hex_bind = hex_bind\n", + " self.background_color = random.random(), random.random(), random.random(), 1\n", + " self.bind(pos=self.reposition_control_cell, size=self.resize_control_cell)\n", + " self.text = '({}, {})'.format(self.hex_bind.coords.row, self.hex_bind.coords.col)\n", + "\n", + " def reposition_control_cell(self, obj, value):\n", + " self.pos = self.hex_bind.pos\n", + "\n", + " def resize_control_cell(self, obj, value):\n", + " self.height = self.hex_bind.height * 2\n", + " self.width = self.hex_bind.width * 2\n", + "\n", + "\n", + "class StrategyGameApp(app.App):\n", + " def build(self):\n", + " return StrategyGame()\n", + "\n", + "if __name__ == '__main__':\n", + " StrategyGameApp().run()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What did we learn? \n", + "\n", + "* angle 0 appears to be straight up for a circle or ellipse\n", + "* The radius of the hexagon is 2*height\n", + "* Make sure you fix the aspect ratio of the rectangles you're basing things now\n", + "* " + ] } ], "metadata": { diff --git a/main.py b/main.py index f29b13c..9cfe363 100644 --- a/main.py +++ b/main.py @@ -1,9 +1,11 @@ import collections import random - +import math from kivy import app, properties from kivy.uix import button, label from kivy.uix.floatlayout import FloatLayout +from kivy.graphics import Color, Ellipse, Line +from kivy.logger import Logger MapCoords = collections.namedtuple('MapCoords', ['row', 'col']) @@ -26,9 +28,15 @@ class StrategyGame(FloatLayout): self.main_map.add_widget(hex_cell) # Add overlay conditionally. - if (row % 6 == 2 and col % 2 == 0) or (row % 6 == 5 and col % 2 == 1): + if (row % 6 == 1 and col % 2 == 1) or (row % 6 == 4 and col % 2 == 0): print('({}, {})'.format(row, col)) - self.add_widget(HexMapControlCell(hex_bind=hex_cell)) + #radius = math.sqrt(hex_cell.width**2 + hex_cell.height**2) + radius = 2*hex_cell.height + with hex_cell.canvas.after: + Color(1,0,1,1) + hex_cell.ell = Line(circle=(hex_cell.x, hex_cell.y,radius, 0, 360, 6), width=2) + hex_cell.bind(pos=hex_cell.update_pos, size=hex_cell.update_pos) + @staticmethod def pick_hex_cell(row, col): @@ -53,11 +61,19 @@ class StrategyGame(FloatLayout): return L() + class HexMapCell(label.Label): def __init__(self, row=0, col=0, **kwargs): super(HexMapCell, self).__init__(**kwargs) self.coords = MapCoords(row, col) + def update_pos(self, instance, value): + Logger.info("StratGame: {}".format(instance)) + #radius = math.sqrt(self.width**2 + self.height**2) + radius = 2*self.height + self.ell.circle = (self.x, self.y, radius, 0, 360, 6) + + class BU(HexMapCell): pass @@ -75,6 +91,7 @@ class R(HexMapCell): pass + class HexMapControlCell(button.Button): def __init__(self, hex_bind=None, **kwargs): super(HexMapControlCell, self).__init__(**kwargs) diff --git a/strategygame.kv b/strategygame.kv index 7efe1d1..37efb25 100644 --- a/strategygame.kv +++ b/strategygame.kv @@ -1,4 +1,5 @@ #:import math math +#:include debug.kv : id: _game @@ -30,36 +31,16 @@ size_hint: 1, .33 background_color: .75, .71, .99, 1 - -: - canvas: +: + pos_hint: {'center_x':.5, 'center_y':.5} + canvas.after: Color: - rgba: (1,1,1,1) - Line: - points: (self.x, self.y, self.right, self.top) - width: 2 -: - canvas: - Color: - rgba: (1,1,1,1) - Line: - points: (self.x, self.top, self.right, self.y) - width: 2 -: - canvas: - Color: - rgba: (1,1,1,1) - Line: - points: (self.x, self.y, self.x, self.top) - width: 2 -: - canvas: - Color: - rgba: (1,1,1,1) - Line: - points: (self.right, self.y, self.right, self.top) - width: 2 + rgba: 1,1,1,1 + Ellipse: + segments: 6 + pos: self.pos + size: min(self.width, self.height), min(self.width, self.height) : size_hint: 1, None - height: self.width / math.sqrt(3) + height: self.width / math.sqrt(3) \ No newline at end of file From 8b5b258be757a93a6601bc9ce493481653c4b23d Mon Sep 17 00:00:00 2001 From: Amy Wooding Date: Sat, 4 Jun 2016 23:04:53 -0700 Subject: [PATCH 19/19] added random colours to the hexagons --- Making a Wargame.ipynb | 18 +++++++++++-- main.py | 59 ++++++++++-------------------------------- strategygame.kv | 2 +- 3 files changed, 31 insertions(+), 48 deletions(-) diff --git a/Making a Wargame.ipynb b/Making a Wargame.ipynb index 614b7f2..4589815 100644 --- a/Making a Wargame.ipynb +++ b/Making a Wargame.ipynb @@ -1110,10 +1110,24 @@ "What did we learn? \n", "\n", "* angle 0 appears to be straight up for a circle or ellipse\n", - "* The radius of the hexagon is 2*height\n", + "* The radius of the hexagon is $2*height$ for a pointed top hexagon, and for flat top, the radius of the hexagon is $2*width$\n", "* Make sure you fix the aspect ratio of the rectangles you're basing things now\n", - "* " + "* segments are inscribed **inside** the circle\n", + "* tiling problems are hard!!! get a mathematician.\n", + "* there is a utility for hex codes for colours\n", + "* draw the hexagon using a Line with a circle to make an outline instead of an Ellipse\n", + "\n", + "Cleaned some stuff up and added colours to the hexagons. " ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/main.py b/main.py index 9cfe363..fb38a99 100644 --- a/main.py +++ b/main.py @@ -1,11 +1,14 @@ import collections import random import math + from kivy import app, properties from kivy.uix import button, label from kivy.uix.floatlayout import FloatLayout from kivy.graphics import Color, Ellipse, Line from kivy.logger import Logger +import kivy.utils +from kivy.vector import Vector MapCoords = collections.namedtuple('MapCoords', ['row', 'col']) @@ -24,7 +27,7 @@ class StrategyGame(FloatLayout): col = region % self.map_cols # Add hex cells to make up the map. - hex_cell = self.pick_hex_cell(row=row, col=col) + hex_cell = HexMapCell() self.main_map.add_widget(hex_cell) # Add overlay conditionally. @@ -32,65 +35,31 @@ class StrategyGame(FloatLayout): print('({}, {})'.format(row, col)) #radius = math.sqrt(hex_cell.width**2 + hex_cell.height**2) radius = 2*hex_cell.height + solid_x = hex_cell.x - hex_cell.height*2 + solid_y = hex_cell.y - hex_cell.height*2 + solid_size = (4*hex_cell.height, 4*hex_cell.height) with hex_cell.canvas.after: Color(1,0,1,1) hex_cell.ell = Line(circle=(hex_cell.x, hex_cell.y,radius, 0, 360, 6), width=2) + Color(*kivy.utils.get_random_color(alpha = .5)) + hex_cell.solid = Ellipse(pos = (solid_x, solid_y), size = solid_size, segments = 6 ) hex_cell.bind(pos=hex_cell.update_pos, size=hex_cell.update_pos) - @staticmethod - def pick_hex_cell(row, col): - row_mod = row % 6 - if col % 2 == 0: - if row_mod == 0: - return BU() - elif row_mod in (1, 2): - return L() - elif row_mod == 3: - return TD() - elif row_mod in (4, 5): - return R() - else: - if row_mod == 0: - return TD() - elif row_mod in (1, 2): - return R() - elif row_mod == 3: - return BU() - elif row_mod in (4, 5): - return L() - - - class HexMapCell(label.Label): def __init__(self, row=0, col=0, **kwargs): super(HexMapCell, self).__init__(**kwargs) self.coords = MapCoords(row, col) def update_pos(self, instance, value): - Logger.info("StratGame: {}".format(instance)) #radius = math.sqrt(self.width**2 + self.height**2) radius = 2*self.height + solid_x = self.x - self.height*2 + solid_y = self.y - self.height*2 + solid_size = (4*self.height, 4*self.height) self.ell.circle = (self.x, self.y, radius, 0, 360, 6) - - - -class BU(HexMapCell): - pass - - -class TD(HexMapCell): - pass - - -class L(HexMapCell): - pass - - -class R(HexMapCell): - pass - - + self.solid.pos = (solid_x, solid_y) + self.solid.size = solid_size class HexMapControlCell(button.Button): def __init__(self, hex_bind=None, **kwargs): diff --git a/strategygame.kv b/strategygame.kv index 37efb25..886890a 100644 --- a/strategygame.kv +++ b/strategygame.kv @@ -1,5 +1,5 @@ #:import math math -#:include debug.kv +##:include debug.kv : id: _game