-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathTerrainManager.py
146 lines (118 loc) · 4.26 KB
/
TerrainManager.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import TerrainClass
from panda3d.core import PandaNode, NodePath
import math
import random
class TerrainManager (object):
class TerrainElement():
def __init__(self,terrain,xPos,yPos):
self.terrain=terrain
self.xPos=xPos
self.yPos=yPos
def __init__(self):
self.terrainElements=[]#holds all terrainElements
self.terrainGrid=[[]]#holds terrainElements as they will be displayed
self.dirty=True # the terrainGrid should be refreshed on next update
self.rootNode = PandaNode("terrainManager root")
self.root = NodePath( self.rootNode )
self.terrainSize=257 #first=textureSize
self.scale=16
#locatoin that whereIsCamera returned last frame
self.lastCamearaLocation = (0,0)
self.currentCamearaLocation = (0,0)
self.defaultBlockSize=64
def whereIsCamera (self):
'''where is the camera over the terrain
returns a tuple of (x,y) for the grid location'''
cam = base.camera.getPos()
cam = (int (cam[0]) /(self.scale*self.terrainSize) ,
int(cam[1]) /(self.scale*self.terrainSize ))
return cam
def newTerrainPart( self, heightMap, textureMap):
'''create a new terrain element, when update is called they will be
reorganized into a terrain grid and displayed'''
self.dirtyGrid=True
newPart = TerrainClass.TerrainClass(heightMap,heightMap)
newPart.setMonoTexture( textureMap )
newPart = self.TerrainElement( newPart, None, None )
self.terrainElements.append( newPart )
def getBlockSize(self):
return self.terrainElements[0].terrain.getBlockSize()
def setBlockSize( self, size=None ):
if size is None:
print "current block size:",self.getBlockSize()
size = int ( raw_input( " input new blockSize:") )
for i in self.terrainElements:
i.terrain.setBlockSize( size )
return
def gridsAway( self, src, dst):
'''src==tuple of starting grid location
dst == tuple of ending grid location
returns an integer containing number of grids seperating
the two locations, does not take into account differences between
diagnal and strait distance'''
toRet = (abs(src[0]-dst[0]),
abs(src[1]-dst[1]))
toRet = abs( toRet[0]+toRet[1])
return toRet
def autoBlockSizes(self):
'''set the block sizes of the terrains based on the distance from
the camera'''
here = self.currentCamearaLocation
default = self.defaultBlockSize
if here == default:
'''don't try to update if nothing changed'''
return
for row in range( len( self.terrainGrid ) ):
for col in range( len( self.terrainGrid[row] ) ):
new = default #defalut is defaultBlockSize
distance = self.gridsAway( here, (row,col) )
if distance > 2:
new = new*(2**(distance-2))
new = min ( self.terrainSize-1 , new )
self.terrainGrid[row][col].setBlockSize( new )
def update( self, task=None):
'''update the terrain elements that need it
and generate the terrain grid if it needs to be done ( is dirty)'''
def isPerfectSquare( x ):
y = int( math.sqrt(x) ) **2
return y == x
def makeTerrainGrid():
self.terrainGrid=[] # empty list of lists
self.dirty=False
if not isPerfectSquare( len(self.terrainElements) ):
raise Exception( "can't deal with non perfect square number "+
"of terrains")
side = int( math.sqrt( len( self.terrainElements ) ) )
'''make terrain grid'''
for i in xrange(side):
y = i*self.terrainSize
self.terrainGrid.append([])
for j in xrange(side):
x = j*self.terrainSize
element = self.terrainElements[i*side+j]
element.x=x
element.y=y
self.terrainGrid[i].append( element.terrain )
element.terrain.getRoot().setPos( element.x, element.y,0 )
elementNode= element.terrain.getRoot().getNode(0)
self.rootNode.addChild(elementNode)
#start the update
'''reset camera locations'''
self.lastCamearaLocation= self.currentCamearaLocation
self.currentCamearaLocation= self.whereIsCamera()
if self.lastCamearaLocation!= self.currentCamearaLocation:
self.autoBlockSizes()
if self.dirty:
makeTerrainGrid()
self.root.setScale(self.scale, self.scale, self.scale)
#update one of the terrains
side = len( self.terrainGrid )
updateX = random.randint(0,side-1)
updateY = random.randint(0,side-1)
self.terrainGrid[updateX][updateY].asyncUpdate()
if task is None:
return
else:
return task.cont
def getRoot(self):
return self.root