hi again
have made a test scenario where a bunch of ships flt from waypoint to waypoint and uses bullet for the thrust.
however for some reason the ships all bounce off a non-existent shape that i didn’t create.
my code is quite a hacked bundle of information, so if its bad sorry. still help would be appreciate.
__author__ = 'fam'
# space vessels that journey from one spehere to another
# no bullet to start with
import direct.directbase.DirectStart
from panda3d.core import *
from direct.gui.DirectGui import *
from panda3d.core import Vec3, Vec4
from direct.interval.IntervalGlobal import *
from panda3d.core import Quat
from direct.task import Task
from direct.showbase.DirectObject import DirectObject
from direct.showbase.InputStateGlobal import inputState # get keyboard & mouse inputs
from panda3d.bullet import BulletWorld
from panda3d.bullet import BulletPlaneShape
from panda3d.bullet import BulletBoxShape
from panda3d.bullet import BulletSphereShape
from panda3d.bullet import BulletRigidBodyNode
from panda3d.bullet import BulletDebugNode
from panda3d.core import BitMask32
import random
import time
class Fleet():
fleet_list = []
def __init__(self, bulletworld,size = 5):
#print ("making fleet")
self.fleet_size = size
self.bullet_world = bulletworld
self.make_fleet()
self.target_list = []
self.curr_target = 0
def random_targets(self,number = 5):
self.numTargets = number
for each in range(0,self.numTargets):
self.target_list.append(random.randrange(-10,10),random.randrange(-10,10),random.randrange(-10,10) )
print ("target list is", self.target_list)
def make_fleet(self):
self.tempz = []
self.tempC = []
numba = self.fleet_size
tpoz = [random.randint(6,6),random.randint(-7,7),random.randint(-12,12)]
for number in range(0,numba):
#print ("number is", number)
ship1 = Craft(self.bullet_world)
t = ship1.load_ship()
Fleet.fleet_list.append(t)
self.tempz.append(t)
self.tempC.append(ship1)
self.tempz[number].setPos(tpoz[0]+(2*number), tpoz[1]+random.random()*3,tpoz[2]+random.random()*3)
#self.tempz[number].setPos(random.randint(-6,6),random.randint(-9,7),random.randint(-8,8))
#print (tempz)
return self.tempz
def get_ships(self):
return self.tempz
def fly_fleet(self,dt):
for shipz in self.tempC:
shipz.fly(dt)
class Craft():
ship_list = []
arrived_count = 0
targetPos = [(10,0,5),(-10,0,10),(14,5,15)]
target_count = 0
target_iter = 0
mask1 = BitMask32.allOn()
mask2 = BitMask32.allOff()
mask3 = BitMask32.bit(2)
mask4 = BitMask32.bit(5)
mask5 = BitMask32(0x3)
craft_types = ["rocket1","spacestation","cruiser"]
def __init__(self,bulletworld):
self.bulletWorld = bulletworld
#print ("making ships")
self.type = 0 #default is rocket1
self.timeScale = 1
self.sizescale = 1
self.orbitscale = 1
self.accel_rate = 1
self.decel_rate = 5
self.max_speed = 2
self.turn_rate = random.randint(2,7)
self.health = 100
self.speedNow = 0.0
self.curr_waypoint = 0
self.waypoints = [(10,0,0),(-12,-4,-5),(14,5,6)]
#[(random.randrange(-10,10),random.randrange(-5,5),random.randrange(-5,5)),(random.randrange(-10,10),random.randrange(-5,5),random.randrange(-5,5)),(2+random.randrange(-10,10),random.randrange(-5,5),random.randrange(-5,5))]
setupTarget = self.makeTarget()
self.cruise_speed = self.max_speed/.75
self.ID = len(Craft.ship_list)
self.armour=150
self.flyable = True
self.startCount = 0
self.hasArrived = 0
#print ("ship ID is " , self.ID)
def setType(self,type):
self.type = type
def setPosition(self,x,y,z):
self.ship_root.setPos(x,y,z)
def makeTarget(self):
self.target = render.attachNewNode('target' + str(len(Craft.ship_list)))
self.target_mesh = loader.loadModel('box')
self.target_mesh.reparentTo(self.target)
#self.target.setPos(Craft.targetPos[Craft.target_count][0],Craft.targetPos[Craft.target_count][1],Craft.targetPos[Craft.target_count][2])
self.target.setPos(self.waypoints[self.curr_waypoint][0],self.waypoints[self.curr_waypoint][1],self.waypoints[self.curr_waypoint][2])
print ("traget ", Craft.targetPos[0])
Craft.target_count += 1
self.target.setRenderModeWireframe()
if Craft.target_count >2:
Craft.target_count = 0
return self.target
def moveTarget(self,x,y,z):
self.target.setPos(x,y,z)
def load_ship(self):
print ("drawing ship", len(Craft.ship_list))
print ("")
shape = BulletBoxShape(Vec3(0.5,0.5,0.5))
self.ship_root = render.attachNewNode(BulletRigidBodyNode('shipNode'+str(len(Craft.ship_list))))
self.ship = loader.loadModel(Craft.craft_types[0])
self.ship_root.node().setMass(1)
self.ship_root.node().addShape(shape)
Craft.ship_list.append(self.ship_root)
self.ship.reparentTo(self.ship_root)
#self.ship_root.setPos(0,0,0)
self.ship.setHpr(180,0,0)
self.ship_root.setScale(0.1*self.sizescale)
self.bulletWorld.attachRigidBody(self.ship_root.node())
self.ship_root.setCollideMask(Craft.mask2)
return self.ship_root
def loadParticleConfig(self, file):
#Start of the code from steam.ptf
self.p.cleanup()
self.p = ParticleEffect()
self.p.loadConfig(Filename(file))
#Sets particles to birth relative to the teapot, but to render at toplevel
self.p.start(self.t)
self.p.setPos(3.000, 0.000, 2.250)
def load_cruiser(self):
print ("drawing cruiser", len(Craft.ship_list))
print ("")
shape = BulletBoxShape(Vec3(0.5,0.5,0.5))
self.ship_root = render.attachNewNode(BulletRigidBodyNode('cruiserNode'+str(len(Craft.ship_list))))
self.ship = loader.loadModel(Craft.craft_types[2])
self.ship_root.node().setMass(10)
self.ship_root.node().addShape(shape)
Craft.ship_list.append(self.ship_root)
self.ship.reparentTo(self.ship_root)
#self.ship_root.setPos(0,0,0)
self.ship.setHpr(180,0,0)
self.ship_root.setScale(2*self.sizescale)
self.bulletWorld.attachRigidBody(self.ship_root.node())
self.ship_root.setHpr(random.randint(0,220),0,0)
return self.ship_root
def fly(self,dt):
#check angle
self.dt = dt
angleBase = self.ship_root.getHpr()
angleTarget = self.pointAt(self.ship_root,self.target)
angleDiff = angleBase - angleTarget
total_angle = angleDiff[0]+angleDiff[1]
dist = self.get_distance(self.ship_root,self.target)
tForce = 3.0
if self.startCount == 0:
self.startCount = time.clock()
self.pos1 = self.ship_root.getPos()
if time.clock() - self.startCount >= 1:
self.pos2 = self.ship_root.getPos()
timePast = time.clock() - self.startCount
calcDist = self.pos2 - self.pos1
distL = calcDist.length()
self.speedNow = distL/timePast
#print ("at dist", dist, "for ship ID" , self.ID, "current speed is" , self.speedNow , "over", timePast)
self.startCount = 0
if dist >=7:
tForce = 10.0
elif dist <6 and dist > 4:
tForce = 5.0
elif dist <= 2 and self.speedNow > 0:
tForce = 1
elif dist<=1:
self.hasArrived = 1
Craft.arrived_count += 1
self.curr_waypoint += 1
self.ship.setColor(1,0,0)
#self.target.setPos(Craft.targetPos[Craft.target_iter][0],Craft.targetPos[Craft.target_iter][1],Craft.targetPos[Craft.target_iter][2])
if self.curr_waypoint >len(self.waypoints):
self.curr_waypoint = 0
tForce = self.speed_limiter(tForce)
if self.hasArrived == 1:
self.change_target()
if abs(total_angle) > 5:
qAngle = self.quat_by_quat(self.ship_root,self.target)
self.turn_towards(self.ship_root,qAngle,self.turn_rate)
elif abs(total_angle) <= 30: # pointing in general direction so start moving
self.move_fowards(self.ship_root,self.target,tForce)
self.obst = self.check_obstacles(10)
# print ("obstacle is selfobst ", self.obst)
self.safe_dist = self.max_speed
def speed_limiter(self,tforce):
if self.speedNow >= self.max_speed:
self.ship_root.node().setLinearVelocity(self.max_speed)
return 0
else:
return tforce
def change_target(self):
self.target.setPos(Craft.targetPos[Craft.target_iter][0],Craft.targetPos[Craft.target_iter][1],Craft.targetPos[Craft.target_iter][2])
self.hasArrived = 0
def take_evasive(self,enemypos):
print ("enemy ahead at", enemypos)
def check_safe_distance(self,base,target):
#in a nutshell get the pos where the ship will be in vec * time
# time to deceltime = dist/decel_speed
time_decel = target.getPos()/self.decel_rate
def intercept_pos(self,base,target,speed):
temp_pos = target.getPos()
temp_dir = target.getHpr()
temp_speed = speed
dist = self.get_distance(base,target)
bullets_speed = 1.0
temp_time = dist/bullets_speed
temp_vec = render.getRelativeVector(node,Vec3(0,1,0))
projected_pos = temp_vec * temp_time
return projected_pos
def check_obstacles(self,dist = 50):
pFrom = self.ship_root.getPos()
pTo = pFrom + Vec3(0,1,0)*dist
result = self.bulletWorld.rayTestClosest(pFrom, pTo)
if result.hasHit() == True:
obstacle = result.getNode()
obstaclePos = result.getHitPos()
print ("for ship ID", self.ID," obstacle is ", obstacle, "at ",obstaclePos)
tPos = (self.ship_root.getPos() - obstaclePos).length()
return obstacle
def get_distance(self,base,target):
target_vec = base.getPos() - target.getPos()
distance = target_vec.length()
return distance
def get_dist_vec3(self,base,target):
target_vec = base - target
distance = target_vec.length
return distance
def quat_by_quat(self,base,obj2):
#takes 2 objects
# gets pos and quat of obj1
# get required quat to point at obj2
#return difference
obj1 = base
quat1 = obj1.getQuat()
pos1 = obj1.getPos()
obj1Dir = quat1.getForward()
obj1Dir.normalize()
#v = obj1Dir
vec2obj2 = obj2.getPos() - pos1
vec2obj2.normalize()
angleTowards = self.pointAt(base,obj2)
#print ("quat1 and asngeltwards" , quat1, angleTowards)
angleinQuat = Quat()
angleinQuat.setHpr(Vec3(angleTowards))
#print ("angle in quat is ", angleinQuat)
#qSubq = quat1 - angleinQuat
#print ("angle to turn is ",qSubq)
#obj1.setQuat(angleinQuat)
return angleinQuat
def pointAt(self, base,target):
self.tempNode = render.attachNewNode('tempNode')
self.tempNode.setPos(base.getPos())
self.tempNode.setHpr(base.getHpr())
self.tempNode.lookAt(target)
tempVec = self.tempNode.getHpr()
#print ("tempVec is", tempVec)
return tempVec
def turn_towards(self,base,angle,turnspeed):
myInterval1 = base.hprInterval(turnspeed, angle)
seq = Parallel(myInterval1)
seq.start()
def calc_speed(self):
"""returns a point in time. do it twice to work out speed"""
tPos = self.ship_root.getPos()
timeSlice = time.clock()
return tPos, timeSlice
def move_fowards(self,base,target,forceT = 5.0):
force = Vec3(0, 0, 0) # Forward
torque = Vec3(0, 0 ,0)
target_vec = base.getPos() - target.getPos()
#distance = target_vec.length()
#curVec = render.getRelativeVector(base,Vec3(0,1,0))
force.setY(forceT)
base.node().setActive(True)
torque = render.getRelativeVector(base,torque)
base.node().applyTorque(torque)
force = render.getRelativeVector(base, force)
#print ("force is", force , " for ID" , base)
base.node().applyCentralForce(force)
def decel(self):
curSpeed = self.speedNow
decelRate = -2
class Solar_body():
body_list = []
def __init__(self):
print ("making planets")
self.timeScale = 1
self.sizescale = 1
self.orbitscale = 1
self.planetsScales = [1,2]
newSys = self.gen_system()
def gen_system(self,planetNum= 4):
self.num_planets = planetNum
#newSun = self.make_sun()
for each in range(0,self.num_planets):
chanceMoon = random.random()
hasMoon = False
if chanceMoon >0.4:
hasMoon = True
tempX=random.randint(10*each,20*each)
tempSize = random.randrange(self.planetsScales[0],self.planetsScales[1])
newPlanet = self.loadPlanets(tempX,tempSize,hasMoon)
Solar_body.body_list.append(newPlanet)
def make_sun(self,size=3):
self.sun = loader.loadModel('planet_sphere')
self.sun_tex = loader.loadTexture("models/sun_1k_tex.jpg")
self.sun.setTexture(self.sun_tex, 1)
self.sun.reparentTo(render)
self.sun.setScale(size * self.sizescale)
def loadPlanets(self,posi,scale,hasMoon):
planet_pos = posi
planet_scale = scale
self.orbit_root_planet = render.attachNewNode('orbit_planet' + str(len(Solar_body.body_list)))
self.planet1 = loader.loadModel("models/planet_sphere")
self.p1_tex = loader.loadTexture("models/mercury_1k_tex.jpg")
self.planet1.setTexture(self.p1_tex, 1)
self.planet1.reparentTo(self.orbit_root_planet)
self.planet1.setPos( planet_pos * self.orbitscale, 0, 0)
self.planet1.setScale(planet_scale * self.sizescale)
if hasMoon == True:
print ("has moon")
self.orbit_root_moon = self.orbit_root_planet.attachNewNode('orbit_planet' + str(len(Solar_body.body_list)))
self.moon = loader.loadModel("models/asteroid")
self.moon_tex = loader.loadTexture("models/moon_1k_tex.jpg")
self.moon.setTexture(self.p1_tex, 1)
self.moon.reparentTo(self.orbit_root_moon)
self.moon.setPos( random.randrange(-3,3), -3, -5)
self.moon.setScale((planet_scale/2) * self.sizescale)
return self.orbit_root_planet
class World(DirectObject):
AI_list = []
def __init__(self):
base.setBackgroundColor(0.31,0.351,0.453)
base.disableMouse()
camera.setPos(0,60,5)
camera.lookAt(5,5,0)
self.ship_list = []
base.enableParticles()
base.wireframeOn()
self.timeScale = 1
self.sizescale = 1
self.orbitscale = 1
self.accept('escape',self.doExit)
inputState.watchWithModifiers('forward', 'w')
inputState.watchWithModifiers('left', 'a')
inputState.watchWithModifiers('back', 's')
inputState.watchWithModifiers('right', 'd')
inputState.watchWithModifiers('up', 'q')
inputState.watchWithModifiers('down', 'z')
inputState.watchWithModifiers('mouseTorque', 'mouse3')
inputState.watchWithModifiers('slow','space')
inputState.watchWithModifiers('accelerate','lshift')
inputState.watchWithModifiers('pickIt','mouse1')
taskMgr.add(self.gameLoop, "gameLoop")
self.all_fleets = []
self.startBullet()
self.setLight()
planets = Solar_body()
fl1 = Fleet(self.world,5)
cruiser1 = Craft(self.world)
#self.fleet1 = Craft()
#self.fleet1.create_fleet(4)
#print ("fl1 is", fl1)
#print ("all fleets are", self.all_fleets)
World.AI_list.append(fl1)
def turn_debug_on(self):
debugNode = BulletDebugNode('Debug')
debugNode.showWireframe(True)
debugNode.showConstraints(True)
debugNode.showBoundingBoxes(True)
debugNode.showNormals(True)
debugNP = render.attachNewNode(debugNode)
#self.world.setDebugNode(debugNP.node())
debugNP.show()
self.world.setDebugNode(debugNP.node())
def startBullet(self):
print ("starting bullet")
self.world = BulletWorld()
self.world.setGravity(Vec3(0,0,0))
self.turn_debug_on()
def doExit():
sys.Exit(1)
def gameLoop(self,task):
dt = globalClock.getDt()
self.processInput(dt)
#frameTime = globalClock.getFrameTime()
self.world.doPhysics(dt, 100, 1./500.)
self.think_AI(dt)
return Task.cont
def think_AI(self,dt):
num_ai = len(World.AI_list)
for each in range(0,num_ai):
temp = World.AI_list[each].get_ships()
print ("temp ships is ",temp)
World.AI_list[each].fly_fleet(dt)
def processInput(self,dt):
moveto=[]
force = Vec3(0, 0, 0) # Forward
torque = Vec3(0, 0 , 0)
if inputState.isSet('forward'):
force.setY(1.0)
if inputState.isSet('back'):
force.setY(-1.0)
if inputState.isSet('right'):
force.setX(-1.0)
if inputState.isSet('left'):
force.setX(1.0)
if inputState.isSet('up'):
torque.setX(0.5)
if inputState.isSet('down'):
torque.setX(-0.5)
if inputState.isSet('slow'):
#print ("camera pos is", self.camX, self.camY , self.camZ)
#angle_change = self.player.node().getAngularVelocity()
#current_speed = self.player.node().getLinearVelocity()
pass
if inputState.isSet('mouseTorque'):
if base.mouseWatcherNode.hasMouse():
pTorque = base.mouseWatcherNode.getMouse()
#print ("torqe X = ", torqX)
#print ("torq Z is ", torqZ)
#spaceS = self.make_space_station(moveto[0],moveto[1],0)
#spaceS.setPos(moveto[0],moveto[1],0)
if inputState.isSet('accelerate'):
force *= 5
if inputState.isSet('pickIt'):
pass
#y=self.pick_object()
#self.player.node().setActive(True)
#torque = render.getRelativeVector(self.player, torque)
#self.player.node().applyTorque(torque)
#force = render.getRelativeVector(self.player, force)
#self.player.node().applyCentralForce(force)
#self.player.node().applyTorque(torque)
def setLight(self):
plight = PointLight('plight')
plight.setColor(VBase4(.58,.58,.485,1))
plnp = render.attachNewNode(plight)
plnp.setPos(0,0,0)
render.setLight(plnp)
plight.setShadowCaster(False, 512, 512)
self.slight = Spotlight('slight')
self.slight.setColor(VBase4(0.87, 0.7, 0.7, 1))
lens = PerspectiveLens()
self.slight.setLens(lens)
self.slnp = render.attachNewNode(self.slight)
self.slnp.setPos(20,3,50)
self.slnp.lookAt(1,1,1)
render.setLight(self.slnp)
# Use a 512x512 resolution shadow map
self.slight.setShadowCaster(True, 512, 512)
# Enable the shader generator for the receiving nodes
render.setShaderAuto()
w = World()
run()