Repository navigation
Description
Sorry, I couldn't find convenient resources for how to migrate Processing2 Python code to Processing3.
The pyde code below works fine in processing2, and fails with the following (useless to me) error in Processing3:
processing.app.SketchException: java.lang.NullPointerException
at processing.core.PApplet.dispose(PApplet.java:3823)
at processing.core.PApplet.die(PApplet.java:3734)
at processing.core.PApplet.die(PApplet.java:3744)
at processing.core.PApplet.loadFont(PApplet.java:6347)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.python.core.PyReflectedFunction.call(PyReflectedFunction.java:188)
at org.python.core.PyReflectedFunction.call(PyReflectedFunction.java:206)
at org.python.core.PyObject.call(PyObject.java:497)
at org.python.core.PyObject.call(PyObject.java:501)
at org.python.core.PyMethod.call(PyMethod.java:141)
at org.python.pycode._pyx11.f$0(conway3.pyde:1)
at org.python.pycode._pyx11.call_function(conway3.pyde)
at org.python.core.PyTableCode.call(PyTableCode.java:171)
at org.python.core.PyCode.call(PyCode.java:18)
at org.python.core.Py.runCode(Py.java:1614)
at org.python.core.Py.exec(Py.java:1658)
at org.python.pycode._pyx10.f$0(/Users/pokey/projects/Processing/conway3/conway3.pyde:96)
at org.python.pycode._pyx10.call_function(/Users/pokey/projects/Processing/conway3/conway3.pyde)
at org.python.core.PyTableCode.call(PyTableCode.java:171)
at org.python.core.PyCode.call(PyCode.java:18)
at org.python.core.Py.runCode(Py.java:1614)
at org.python.core.Py.exec(Py.java:1658)
at org.python.util.PythonInterpreter.exec(PythonInterpreter.java:276)
at jycessing.PAppletJythonDriver.processSketch(PAppletJythonDriver.java:230)
at jycessing.PAppletJythonDriver.findSketchMethods(PAppletJythonDriver.java:590)
at jycessing.Runner.runSketchBlocking(Runner.java:398)
at jycessing.mode.run.SketchRunner.lambda$2(SketchRunner.java:112)
at java.lang.Thread.run(Thread.java:748)at jycessing.mode.run.SketchRunner.convertPythonSketchError(SketchRunner.java:224)
at jycessing.mode.run.SketchRunner.lambda$2(SketchRunner.java:119)
at java.lang.Thread.run(Thread.java:748)
Line 96 of conway3.pyde is referenced, but is a blank line in the actual code. I have no way to relate the Java errors to the python.
Since this interface won't let me attach a file, I'll try to just cut/paste it here (neither the .pyde, nor the .pyde.gz would attach).
# Converted to processing.py from the java example at processing.org by pokey and jacob, 26-Aug-2015
# Creeping elegance by pokey over the next several days (verbosity, color sets, speeds, help message, pre-sets...)
# Creeping elegance requested by Jake to add independent "die of old-age" option: May-2017
# Size of cells
cellSize = 10
# How likely for a cell to be alive at start (in percentage)
probabilityOfAliveAtStart = 15.0
# Variables for timer
interval = 100
lastRecordedTime = 0
# Colors for active/inactive cells
# ("Resistor", [black, brown, red, orange, yellow, green, blue, violet, gray, white]
def NewColor3((r,g,b)):
'''blend colors a'la fractals.py.'''
minVal = 80 # must be even!
maxVal =191 # must be odd!
incVal = 12 # must be even!
if (r%2 == 0):
if (r >= (maxVal - 1)):
r = maxVal
else:
r = r + incVal
if (g%2 == 0):
if (g >= (maxVal - 1)):
g = maxVal
else:
g = g + incVal
else:
if (g <= (minVal + 1)):
g = minVal
else:
g = g - incVal
else:
if (r <= (minVal + 1)):
r = minVal
else:
r = r - incVal
if (b%2 == 0):
if (b >= (maxVal - 1)):
b = maxVal
else:
b = b + incVal
else:
if (b <= (minVal + 1)):
b = minVal
else:
b = b - incVal
return (r,g,b)
# NewColor3
allColors = ['#000000'] # start with black and count by 4's to reduce the array size and make distinguishable colors
nextRGB = (101,111,121)
while True:
(i,j,k) = nextRGB
hexR = hex(i)
hexG = hex(j)
hexB = hex(k)
hexRGB = '#'+hexR[-2:]+hexG[-2:]+hexB[-2:]
if hexRGB not in allColors:
allColors.append(hexRGB)
nextRGB = NewColor3((i,j,k))
#print (hexRGB)
else:
break
# allColors.append('#F0F0F0')
colorSets = [#("Name", ['list','of','colors'])
("Too Many ("+str(len(allColors))+")", allColors),
("Todd", ['#000000', '#964A00', '#FF0000', '#FF7F00', '#FFFF00', '#DFFF00', '#00FF00', '#40E0D0', '#00FFFF', '#007FFF', '#3333FF', '#7F00FF', '#FF00FF', '#FF7F90', '#A0A0A0', '#E0E0E0']),
("Jake", ['#000000', '#964B00', '#FF0000', '#FF5500', '#FFFF00', '#55FF00', '#00FF00', '#00FF55', '#00FFFF', '#0055FF', '#1111FF', '#5500FF', '#FF00FF', '#FF0055', '#808080', '#F0F0F0']),
("Resistor", ['#000000', '#964B00', '#FF0000', '#FF5500', '#FFFF00', '#00FF00', '#3333FF', '#5500FF', '#808080', '#F0F0F0']),
("15 Shades of Gray", ['#000000', '#222222', '#323232', '#424242', '#525252', '#626262', '#727272', '#828282', '#929292', '#A2A2A2', '#B2B2B2', '#C2C2C2', '#D2D2D2', '#E2E2E2', '#F2F2F2']),
("Mono-Green",['#000000', '#00C800']),
]
colorIndex = 0
(colorMap, colorList) = colorSets[colorIndex]
# Preset Patterns ("Name",(bounding, tuple),[(list,of),(x,y),(coordinates,to),(mark,alive)])
# Null List forces randomization of cells!
presetList = [
("Random",(0,0),[]),
("Exploder",(5,5),[(0,0),(2,0),(4,0),(0,1),(4,1),(0,2),(4,2),(0,3),(4,3),(0,4),(2,4),(4,4)]),
("Tumbler",(7,6),
[(1,0),(2,0),(4,0),(5,0),(1,1),(2,1),(4,1),(5,1),(2,2),(4,2),(0,3),
(2,3),(4,3),(6,3),(0,4),(2,4),(4,4),(6,4),(0,5),(1,5),(5,5),(6,5)]),
("Glider Gun",(38,15),
[(0,2),(1,2),(0,3),(1,3),(9,2),(10,2),(8,3),(10,3),(8,4),(9,4),(16,4),(17,4),(16,5),
(18,5),(16,6),(23,0),(24,0),(22,1),(24,1),(22,2),(23,2),(34,0),(35,0),(34,1),(35,1),
(35,7),(36,7),(35,8),(37,8),(35,9),(24,12),(25,12),(26,12),(24,13),(25,14)])
]
presetIndex = 0
(presetName, presetTuple, presetCoord) = presetList[presetIndex]
# Preset Rules. Set AgeBased FALSE to use possible counts of neighbors in birth,sustain lists.
# When AgeBased TRUE, then use min and max % of sum of ages needed to sustain life in birth,sustain lists.
# No more than 10 rules are recommended, as it is, they may fall off the bottom of small screens.
# ("Name",AgeBased=False,[#,of,neighbors,to,be,born],[#,of,neighbors,to,stay,alive])
# ("Name",AgeBased=True ,[min % sum of ages] ,[max % sum of ages])
ruleSets = [
("Conway ",False,[3],[2,3]),
("HighLife",False,[3,6],[2,3]),
("Todd Neighbor",False,[3,5,7],[1,3,5,7]),
("Todd Neighbor",False,[4,6],[2,3,5,7]),
("Todd Neighbor",False,[4,6],[2,3,4,5]),
("Todd Neighbor",False,[4,3],[2,5]),
("Todd AgeBased",True,[0.7854],[2.3562]),
("Todd AgeBased",True,[0.5],[15]),
("Todd AgeBased",True,[0.3],[1.5]),
("Todd AgeBased",True,[1],[75]),
]
ruleIndex = 0
(ruleName,ageBased,birthList,sustainList) = ruleSets[ruleIndex]
# Fixed-Width Font Me
font = loadFont("Courier-32.vlw")
# Generic initialization...
age = 0
iterations = 0
totalAlive = 0
# Dictionary of cells, Buffer to record the state of the cells and use this while changing the others in the interations
cells = {}
cellsBuffer = {}
# Booleans to remember pause state, and toroidal boundary request, show text while running, show help message for keys.
toroid = True
pause = False
verbose= True
help = False
dieOfAge=False
def randomCells():
'''void function to randomize cells, once, so you don't have to init them in 2 places'''
global cells, cellSize, probabilityOfAliveAtStart
clearCells()
for x in range (int(width/cellSize)):
for y in range(int(height/cellSize)):
state = int(random (100))
if (state > probabilityOfAliveAtStart):
state = 0
else:
state = state % len(colorList)
cells[(x,y)] = state # Save state of each cell
# end initCells
def setup():
''' void function to initialize board'''
global cells, cellSize, cellsBuffer, font, minAlive, maxAlive
textFont(font,32)
# size (920, 640)
size(displayWidth, displayHeight-42)
wide=int(width/cellSize)
high=int(height/cellSize)
minAlive=wide*high
maxAlive=0
noSmooth()
background('#000000') # Fill in black in case cells don't cover all the windows
randomCells() # start right away with random cells
# end setup
def bufferCells(wide,high):
'''void function to cycle through global arrays to save aside working set'''
global cellsBuffer, cells
for x in range (wide):
for y in range (high):
cellsBuffer[(x,y)] = cells.get((x,y),0)
# end bufferCells
def showHelp():
''' void function to display help message '''
global presetList, ruleSets, font
presetNames = []
for (name,tuple,coordinates) in presetList:
presetNames.append(name)
presetNameString = ",".join(presetNames)
ruleNames = []
for (name, ageBased, births, sustains) in ruleSets:
birthstr = "".join([str(n) for n in births])
sust_str = "".join([str(n) for n in sustains])
ruleNames.append(name+" ["+birthstr+"]["+sust_str+"]")
rulesetNameString = "\n ".join(ruleNames)
textAlign(LEFT,TOP)
background(64)
fill("#FFFF80")
fromLeft = 0
fromTop = 5
messages = [" KEY: ACTION {Note: do not hit Arrow, Meta or Shift keys}",
" h: pause and show this help message",
" v: verbose, show generation, interval, etc.",
" p: pause the action",
" r: randomize cells",
" c: clear cells and reset generation count",
" t: toroidal space",
" d: die of Old Age (default=False; recommend True for Age rules)",
" ,|.: slow down | speed up : 20 ms",
" ;|': slow down | speed up : 100 ms",
" n,<space>: single step an iteration (try when paused)",
" 1234567890: choose a new colormap",
" [|]: backward | forward : preset patterns ["+presetNameString+"]",
" -|=: backward | forward : rulesets (see below)",
" q: quit",
" ",
"RULE: name [birth parameter][life parameter]",
" "+rulesetNameString,
]
for i in range(len(messages)):
text (messages[i], fromLeft, fromTop+i*26)
# end showHelp
def draw():
''' void function to draw grid for cells'''
global lastRecordedTime, cellSize, cells, cellBuffer, verbose, dieOfAge
global colorMap, interval, font, colorIndex, presetName, totalAlive
global ruleName, ageBased, birthList, sustainList, minAlive, maxAlive
wide = int(width/cellSize)
high = int(height/cellSize)
# Draw grid
for x in range(wide): # (int x=0; x<width/cellSize; x++) {
for y in range(high): # (int y=0; y<height/cellSize; y++) {
age = cells.get((x,y),0) # color 0, first element of colorList is dead!
# if agebased, you can die of old age (cycle to start of colors); else stick at max age!
if ageBased:
fill(colorList[age%len(colorList)])
else:
fill(colorList[min(age,len(colorList)-1)]) # alive or dead!
rect (x*cellSize, y*cellSize, cellSize, cellSize)
# Iterate if timer ticks
if (millis()-lastRecordedTime>interval) and (not pause):
iteration()
lastRecordedTime = millis()
# Create new cells manually on pause
if pause:
# This stroke will draw the background grid
if help:
stroke('#000000')
else:
if toroid:
stroke('#207020')
else:
stroke('#702020')
# Map and avoid out of bound errors
if (mousePressed):
# force some delay in doing this to keep things calm (1/3 second)
if (millis()-lastRecordedTime > 333):
xCellOver = int(map(mouseX, 0, width, 0, width/cellSize))
xCellOver = constrain(xCellOver, 0, width/cellSize-1)
yCellOver = int(map(mouseY, 0, height, 0, height/cellSize))
yCellOver = constrain(yCellOver, 0, height/cellSize-1)
# Cycle forward through colors
remember = cells.get((xCellOver,yCellOver),0)
cells[(xCellOver,yCellOver)] = (cells.get((xCellOver,yCellOver),0) + 1) % len(colorList)
# print ("set:",xCellOver,yCellOver,cells[(xCellOver,yCellOver)])
if (remember == 0) and (cells[(xCellOver,yCellOver)] > 0):
totalAlive += 1
elif (remember > 0) and (cells[(xCellOver,yCellOver)] == 0):
totalAlive -= 1
lastRecordedTime = millis()
else:
# And then save to buffer once mouse goes up
# Save cells to buffer (so we opeate with one array keeping the other intact)
bufferCells(wide, high)
# correctly update min/max in pauseMode
minAlive = min(minAlive, totalAlive)
maxAlive = max(maxAlive, totalAlive)
else:
if toroid:
stroke('#003300')
else:
stroke('#330000')
birthString = "".join([str(n) for n in birthList])
sustainString = "".join([str(n) for n in sustainList])
rulesToPrint = ruleName+" ["+birthString+"]["+sustainString+"]"
if verbose:
if toroid:
space = "toroidal"
else:
space = "bounded"
if dieOfAge:
dieMsg= "...by old age."
else:
dieMsg = "eternal life!"
textAlign(LEFT,TOP)
fill('#FFFF80')
text("rules: "+rulesToPrint,5,5)
text("alive: "+str(totalAlive),5,40)
text(" min: "+str(minAlive),5,75)
text(" max: "+str(maxAlive),5,110)
text(" age : "+str(iterations),5,145)
text("delay: "+str(interval),5,180)
text("color: "+str(colorIndex)+", \""+colorMap+"\"",5,215)
text("space: "+space,5,250)
text("death: "+dieMsg,5,285)
text(" set : "+presetName,5,320)
if help:
showHelp()
# end draw
def iteration(): # When the clock ticks
'''void function to calculate next generation of cells
'''
global toroid, cellSize, cells, cellsBuffer, iterations, verbose, dieOfAge
global ruleIndex, birthList, sustainList, ageBased, colorList
global totalAlive, minAlive, maxAlive
wide = int(width/cellSize)
high = int(height/cellSize)
# Save cells to buffer (so we opeate with one array keeping the other intact)
bufferCells(wide, high)
# for statistics if verbose
totalAlive = 0
# Visit each cell:
for x in range (wide):
for y in range (high):
# And visit all the neighbours of each cell
neighbours = 0 # We'll count the neighbours
sumOfAges = 0
nearList = [(-1,-1), (0,-1), (1,-1), (-1,0), (1,0), (-1,1), (0,1), (1,1)] # not (0,0)
for (xx,yy) in nearList:
if toroid: # Modulo math always checks around the edges, and is never out of bounds!
age = cellsBuffer.get(( (x+xx)%wide, (y+yy)%high),0)
if (age > 0):
neighbours += 1 # Check alive neighbours and count them
sumOfAges += age
else: # Make sure you are not out of bounds; out of bounds are always empty neighbors!
if (((x+xx>=0) and (x+xx<wide)) and ((y+yy>=0) and (y+yy<high))):
age = cellsBuffer.get((x+xx,y+yy),0)
if (age > 0):
neighbours += 1 # Check alive neighbours and count them
sumOfAges += age
# if (neighbours > 0):
# print ("how:",x+xx,y+yy,neighbours)
# We've checked the neigbours: apply rules!
age = cellsBuffer.get((x,y),0)
if ageBased: # calculate % sum of ages (normalizing to max agess == 8*(len(colors)-1))
maxAge = 8*(len(colorList)-1)
percentOfAges = float(sumOfAges*100)/float(maxAge)
# print (x,y,maxAge,sumOfAges,percentOfAges) # Comment!
if (percentOfAges >= float(birthList[0]) and percentOfAges <= float(sustainList[0])):
cells[(x,y)] = (age+1) % len(colorList) # Use this to stick age @ max: min (age+1, len(colorList)-1)
totalAlive += 1
else: # Age now cycles back to 0 (dying of old age)
if dieOfAge:
cells[(x,y)] = 0
else:
totalAlive += 1
else: # Neighbor Count Based (traditional) rules
if (age > 0): # The cell is alive: age or kill it if necessary
if (neighbours in sustainList):
if dieOfAge and age >= len(colorList)-1:
cells[(x,y)] = 0
else:
cells[(x,y)] = min( (age+1), (len(colorList)-1) ) # The cell is neither dead, nor doomed, so age it by 1 until max
totalAlive += 1
else:
cells[(x,y)] = 0 # Die unless it has 2 or 3 neighbours (default conway sustain list example)
else: # The cell is dead: make it live if necessary
if neighbours in birthList:
cells[(x,y)] = 1 # Only if it has 3 neighbours (default conway birth list example)
totalAlive += 1
# Keep some statistics to display if you are in verbose mode...
iterations += 1
minAlive = min(minAlive, totalAlive)
maxAlive = max(maxAlive, totalAlive)
# end iteration
def clearCells():
'''void function to clear all cells and reset age counter'''
global cellSize, iterations, cells, minAlive, maxAlive, totalAlive
iterations = 0
wide=int(width/cellSize)
high=int(height/cellSize)
minAlive = wide*high
maxAlive = 0
totalAlive = 0
for x in range(wide):
for y in range(high):
cells[(x,y)] = 0 # Save all to zero
# end clearCells
def keyPressed():
'''void function to determine what to do when we type'''
global pause, toroid, dieOfAge, cellSize, probabilityOfAliveAtStart, cells, colorList, colorSets, verbose
global iterations, colorMap, interval, help, colorIndex, presetList, presetIndex, presetName
global ruleSets, ruleIndex, ruleName, ageBased, birthList, sustainList, minAlive, maxAlive
wide = int(width/cellSize)
high = int(height/cellSize)
if key in 'hH':
pause = help = not help
if help:
textFont(font, 24)
else:
textFont(font, 32)
# Restart: reinitialization of cells
if key in 'rR':
randomCells()
presetName = "Random"
# On/off of pause
if key in 'pP':
pause = not pause
# On/off of toroidal shape
if key in 'tT':
toroid = not toroid
# On/off die of Old Age
if key in 'dD':
dieOfAge = not dieOfAge
# On/off of verbosity
if key in 'vV':
verbose = not verbose
# Clear all
if key in 'cC':
clearCells()
# Single step one generation
if key in ' nN':
iteration()
# Choose ruleSet
if key in '=': # move forward through rules
ruleIndex = (ruleIndex+1)%len(ruleSets)
if key in '-': # move backward through rules
ruleIndex = (ruleIndex-1)%len(ruleSets)
(ruleName,ageBased,birthList,sustainList) = ruleSets[ruleIndex]
# Choose preset
if key in '[]':
if key in '[':
direction = -1
else:
direction = +1
presetIndex = (presetIndex+direction)%len(presetList)
clearCells()
(presetName,(presetX,presetY),coordList) = presetList[presetIndex]
xStart = int(wide/2) - int(presetX/2)
yStart = int(high/2) - int(presetY/2)
if coordList:
for (x,y) in coordList:
cells[(xStart + x, yStart + y)] = 1
else: # empty or null coordList means go random!
randomCells()
# Choose colorSet
if key in '1234567890':
# convert key to integer for indexing; limit indices to modulo len( colorSets )
colorIndex = int(key) % len(colorSets)
(colorMap, colorList) = colorSets[colorIndex]
# Change Speed:
if key in ',':
interval = min (2000, interval+20)
if key in ';':
interval = min (2000, interval+100)
if key in '.':
interval = max (20, interval-20)
if key in '\'':
interval = max (20, interval-100)
# Quit
if key in 'qQ':
exit()
# end keyPressed
#
Activity
jeremydouglass commentedon Dec 17, 2019
Please format code blocks with ``` or with the <> button.
Just quickly guessing, but two things jump out at me:
Line 96 of your code.
loadFont, which is invoked with
Those would be my starting guesses -- that you have a font problem, for example you didn't include that file in the new sketch or it isn't on the new system or it is damaged / invalid / no longer compatible for some reason... and/or or the execution chain around line 96 is where you could start debugging.
toddwayne commentedon Dec 23, 2019
Thanks for several tips -- can do on the <> for code blocks.
Part of my confusion: font=loadFont is at line 122 of the code (by either the processing Editor, or other external editor, an original source of my confusion.
The font file itself (Courier-32.vlw) is in the same relative location for Processing 2 and 3, in the data/ directory. I also found a Courier-30.vlw file. Neither file can be loaded.
I recreated the Courier-32.vlw with the in-built "create font", but I never get past this point: same error.
toddwayne commentedon Dec 23, 2019
I got this running after doing 2 things:
toddwayne commentedon Dec 23, 2019
New Code Snippet:
I'd still like to use something like 'displayHeight-42' to dynamically reduce the height based on screen-size. This allows for the presence of the Mac Menu Bar and the top edge of the Mac Windowing system to appear.