Skip to content

Instantly share code, notes, and snippets.

@fitzterra
Last active August 29, 2015 13:57
Show Gist options
  • Select an option

  • Save fitzterra/9492880 to your computer and use it in GitHub Desktop.

Select an option

Save fitzterra/9492880 to your computer and use it in GitHub Desktop.
Pythonista ball moving on grid test
from scene import *
from random import randrange
from mazy import Maze
class MyScene (Scene):
# Class vars until we find a better place for them
gridStroke = (1.00, 0.50, 0.00)
def __init__(self, rows=5, cols=5):
"""
@param rows: Number of rows in maze
@param cols: Number of columns in maze
"""
self.rows = rows
self.cols = cols
self.margin = 5 # margin around maze
self.wallWidth = 6 # Width of a wall on the inside of a cell
self.debug = False
self.numFrames = 0
def setup(self):
"""
Scene setup method
"""
# Get the full usable area minus margin on both sides
x,y = [s-self.margin*2 for s in self.size.as_tuple()]
# Cell size is the smallest of x/cols and y/rows ratio
self.cellSize = int(min(x/self.cols, y/self.rows))
# Disc size is a third of the cell size
self.discSize = int(self.cellSize/1.5)
# Generate the maze
self.maze = Maze(self.rows, self.cols)
if self.debug:
# Print before we reverse for usage with scene coords
print self.maze
# The scene coords is bottom up while the maze is top down. Reverse rows
# in the maze in place
self.maze.maze.reverse()
# randomly select cell for disc
#dx,dy = (randrange(self.cols), randrange(self.rows))
dx = dy = 0
# calc disc coords for this cell
offs = self.cellSize/2-self.discSize/2
dx = dx*self.cellSize + offs
dy = dy*self.cellSize + offs
self.disc = (dx, dy)
def drawCell(self, row, col):
"""
Draws the cell at row, col from the maze
"""
# Get the scene grid coords
pos = self.CelltoXY(row, col)
# Get the cell
c = self.maze.maze[row][col]
if self.debug:
print "Cell: r%s,c%s - walls: %s" % (row, col, c['walls'])
# Get the x,y coords for the four corners, starting top,left and going
# clockwise, into one list
corners = [pos.x, pos.y+pos.h] # Top left
corners += [pos.x+pos.w, pos.y+pos.h] # Top right
corners += [pos.x+pos.w, pos.y] # Bottom right
corners += [pos.x, pos.y] # Bottom left
# Draw each wall if required, starting North and going clockwise
for w in 'NESW':
if self.debug:
print "corners: %s - wall %s?" % (corners, w)
# Is this wall intact for this cell?
if w in c['walls']:
if self.debug:
print " yes - drawing %s to %s" % (corners[:2],
corners[2:4])
# Draw the wall. The line coords will be the first 4 in corners
line(*corners[:4])
# Rotate the front two coords (corner) to the back of the list. This
# will leave the next 4 coords for the next line in clockwise
# sequence in the front of he corner list
corners = corners[2:] + corners[:2]
# Add rounded corners on all wall ends
i = 0
for e in ['NW', 'NE', 'SE', 'SW']:
if e[0] in c['walls'] or e[1] in c['walls']:
x,y = corners[i*2:i*2+2]
x -= self.wallWidth
y -= self.wallWidth
ellipse(x,y,self.wallWidth*2, self.wallWidth*2)
i += 1
def drawMaze(self):
"""
Draws the maze in self.maze
"""
# Set the stroke color and weight
stroke(*self.gridStroke)
# Wall width is the width of the wall on the inside of the cell, so
# should be multipled since the stroke width is centered around the
# line.
stroke_weight(self.wallWidth*2)
for row in range(self.rows):
# Cycle through each cell in the row
for col in range(self.cols):
# Draw the cell
self.drawCell(row, col)
def drawGrid(self):
stroke(*self.gridStroke)
stroke_weight(1)
# first the columns.
# the column start is at 0 and the height is the number
# of rows * cellSize
y1,y2 = 0,self.rows*self.cellSize
for c in range(self.cols):
# the column line pos is the column * cellSize
x = c*self.cellSize
# draw the west line
line(x+self.margin, y1+self.margin, x+self.margin, y2+self.margin)
# set x for the east line
x += self.cellSize-1
# draw the east line
line(x+self.margin, y1+self.margin, x+self.margin, y2+self.margin)
# now the same for the rows
x1,x2 = 0,self.cols*self.cellSize
for r in range(self.rows):
y = r*self.cellSize
line(x1+self.margin, y+self.margin, x2+self.margin, y+self.margin)
y += self.cellSize-1
line(x1+self.margin, y+self.margin, x2+self.margin, y+self.margin)
def XYtoCell(self, x, y):
'''
determine in which cell the supplied x,y coords are
located.
'''
# remove margin from touch coords
x,y = (x-self.margin, y-self.margin)
# find the row
r = int(y/self.cellSize)
# find thhe column
c = int(x/self.cellSize)
return (c, r)
def CelltoXY(self, r, c):
'''
Returns a Rect object mapped to the scene coords for cell ar row r,
column c.
@param r: The grid/maze row (zero based)
@param c: The grid/maze column (zero based)
'''
# The bottom left coord is the row and col multiplied by the cell size
# plus the margin
x,y = (c*self.cellSize+self.margin, r*self.cellSize+self.margin)
# Return a Rect
return Rect(x, y, self.cellSize, self.cellSize)
def cellRect(self, c, r):
'''
returns a Rect() object definining the cell in
column c, row r
'''
x = c*self.cellSize+self.margin
y = r*self.cellSize+self.margin
return Rect(x, y, self.cellSize, self.cellSize)
def cellEdges(self, c, r):
'''
Returns a tuple consisting of top, left, bottom and right
cell pixel limits. these limits are the cell usable area
within the walls.
For any edge where there is no wall, the value will be -1.
'''
cell = self.maze.maze[r][c]
# get the cell position in pixels
pos = self.cellRect(c, r)
# calculate the edges
top = (pos.y+pos.h-self.wallWidth) if 'N' in cell['walls'] else -1
rgt = (pos.x+pos.w-self.wallWidth) if 'E' in cell['walls'] else -1
bot = (pos.y+self.wallWidth) if 'S' in cell['walls'] else -1
lft = (pos.x+self.wallWidth) if 'W' in cell['walls'] else -1
return (top, rgt, bot, lft)
def discInCells(self):
'''
Returns a list of tuples (c,r) for all cells the disc is in at the moment.
'''
x,y = self.disc
s = self.discSize
cells = []
for corn in [(x,y+s), (x+s,y+s), (x+s,y), (x,y)]:
c = self.XYtoCell(*corn)
if c not in cells:
cells.append(c)
return cells
def showTouch(self):
m = 'x: %s px: %s\ny: %s py: %s'
x,y,px,py = '?', '?', '?', '?'
if self.touches:
t = self.touches.values()[0]
x,y = t.location.as_tuple()
inCell = self.XYtoCell(x,y)
text(str(inCell), x=x+50, y=y+50, alignment=1)
px,py = t.prev_location.as_tuple()
text(m % (x,px,y,py), x=0, y=self.size.h, alignment=3)
def showInfo(self):
m = 'marg: %s\ncellSize: %s' %(self.margin, self.cellSize)
text(m, x=self.size.w/2, y=self.size.h, alignment=2)
def drawDisc(self):
fill(1.00, 0.80, 0.40)
stroke_weight(0)
x,y = self.disc
ellipse(x,y,self.discSize,self.discSize)
fill(*self.gridStroke)
def updatePosition(self):
"""
Checks for movement and updates the disc position
accordingly.
"""
# Nothing to do if screen not touched
if not self.touches:
return
# we only work with the first touch
t = self.touches.values()[0]
# find the cell that was touched
x,y = t.location.x,t.location.y
tCell = self.XYtoCell(x,y)
# find the cell(s) the disc is in
dCells = self.discInCells()
# if the touch is not in one of the cells occupied by the disc, do nothing
if tCell not in dCells:
return
# set the disc position so that it's center is the touch position
x,y = [c-self.discSize/2 for c in (x,y)]
# find the cell edges to make sure the disc is within the cell
edges = self.cellEdges(*tCell)
#m = 'tCell: %s\ndCells: %s\nedges: %s' % (str(tCell), str(dCells), str(edges))
#text(m, x=200, y=self.size.h, alignment=3)
# Limit the disc placement to the cell edges if it tries to move outside the cell
#text('dtop: %s' % str(y+self.discSize),x=x, y=y+self.discSize)
if edges[0]!=-1 and (y+self.discSize)>edges[0]:
y = edges[0]-self.discSize
if edges[1]!=-1 and (x+self.discSize)>edges[1]:
x = edges[1]-self.discSize
if edges[2]!=-1 and y<edges[2]:
y = edges[2]
if edges[3]!=-1 and x<edges[3]:
x = edges[3]
self.disc = (x, y)
def fps(self):
'''
Displays frames/sec
'''
# inc frames
self.numFrames += 1
# calc fps
fps = self.numFrames / self.t
d = 'fps: %5.3f' % fps
text(d, x=self.size.w/2, y=1, alignment=8)
def draw(self):
background(0.50, 0.25, 0.00)
#self.drawGrid()
self.drawMaze()
self.updatePosition()
self.drawDisc()
self.fps()
#self.showInfo()
#self.showTouch()
# Debug is only on for one iteration
self.debug = False
run(MyScene(9, 12))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment