Merge pull request #3 from llfkj/master

drawing hexagons! including filling them with colours.
This commit is contained in:
Dorian Pula 2016-07-16 13:24:38 -04:00 committed by GitHub
commit 0bdf4f126d
3 changed files with 615 additions and 102 deletions

View File

@ -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,23 @@
" 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,
@ -572,7 +565,560 @@
"collapsed": true
},
"outputs": [],
"source": []
"source": [
"%%file strategygame.kv\n",
"\n",
"#:include debug.kv\n",
"\n",
"<StrategyGame>:\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",
"<BU>:\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",
"<TD>:\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",
"<L>:\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",
"<R>:\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": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"Replaced the debug labels and coloured the status and minimap two different ways. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"%%file strategygame.kv\n",
"#:import math math\n",
"\n",
"<StrategyGame>:\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",
"<BU>:\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",
"<TD>:\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",
"<L>:\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",
"<R>:\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",
"<HexMapCell>:\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!!"
]
},
{
"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",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"%%file strategygame.kv\n",
"#:import math math\n",
"#:include debug.kv\n",
"\n",
"<StrategyGame>:\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",
"<Hex@Label>:\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",
"<HexMapCell>:\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$ 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",

68
main.py
View File

@ -1,9 +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'])
@ -22,35 +27,23 @@ 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.
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))
@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()
#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)
class HexMapCell(label.Label):
@ -58,22 +51,15 @@ 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
def update_pos(self, instance, value):
#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)
self.solid.pos = (solid_x, solid_y)
self.solid.size = solid_size
class HexMapControlCell(button.Button):
def __init__(self, hex_bind=None, **kwargs):

View File

@ -1,4 +1,5 @@
#:import math math
##:include debug.kv
<StrategyGame>:
id: _game
@ -30,36 +31,16 @@
size_hint: 1, .33
background_color: .75, .71, .99, 1
<BU>:
canvas:
<Hex@Label>:
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
<TD>:
canvas:
Color:
rgba: (1,1,1,1)
Line:
points: (self.x, self.top, self.right, self.y)
width: 2
<L>:
canvas:
Color:
rgba: (1,1,1,1)
Line:
points: (self.x, self.y, self.x, self.top)
width: 2
<R>:
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)
<HexMapCell>:
size_hint: 1, None
height: self.width / math.sqrt(3)
height: self.width / math.sqrt(3)