Last active
August 29, 2015 13:57
-
-
Save fitzterra/9492880 to your computer and use it in GitHub Desktop.
Pythonista ball moving on grid test
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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