import sys, time, math, random, os from OpenGL.GL import * from OpenGL.GLU import * from OpenGL.GLUT import * from dmsgl import * startDir = os.getcwd() + os.sep prevTime = time.time() camera = OrthoCamera(-50,50, 0,100, -100,100) light = Light() light.position = [0, 1, 2] ballMaterial = Material(diffuse=Color.Grey10, specular=Color.White, shininess=20) ballXform = SimpleTransform(translate=[-50, 0, 0]) cannonMaterial = Material(diffuse=Color.Grey50, shininess=40) cannonXform = SimpleTransform(rotateAngle=45,rotateAxis=[0,0,1],translate=[-50, 0, 0]) mountainMaterial = Material(diffuse=Color.Green) mountainXform = SimpleTransform(rotateAngle=-90, rotateAxis=[1,0,0]) targetMaterial = Material(diffuse=Color.X11['brown']) targetXform = SimpleTransform(translate=[40,5,0]) exploding = False def draw(): Color.X11['LightSkyBlue'].clear() camera.apply() light.apply() ballMaterial.apply() ballXform.pushApply() gluSphere(quadric, 2.0, 32, 16) ballXform.pop() ballMaterial.disable() cannonMaterial.apply() cannonXform.pushApply() glRotatef(90.0, 0.0, 1.0, 0.0) gluCylinder(quadric, 2.5, 2.0, 9.0, 20, 1) cannonXform.pop() cannonMaterial.disable() mountainMaterial.apply() mountainXform.pushApply() gluCylinder(quadric, 25, 0, 60, 10, 1) mountainXform.pop() mountainMaterial.disable() targetMaterial.apply() targetXform.pushApply() if exploding: glTranslatef(0.75*math.cos((prevTime-explodeTime)*50), 0, 0) glutSolidCube(10) targetXform.pop() targetMaterial.disable() glutSwapBuffers() def keyboard(key, x, y): global viewDistance if key == chr(27): sys.exit(0) elif key == GLUT_KEY_UP: cannonXform.rotateAngle += 1 elif key == GLUT_KEY_DOWN: cannonXform.rotateAngle -= 1 elif key == ' ': fire() ballActive = False ballVel = Vector([0,0,0]) ballPos = Vector([-50,0,0]) gravity = Vector([0, -9.8, 0]) fireSpeed = 40 def fire(): global ballActive, ballVel, ballPos ballActive = True ballVel = fireSpeed * Vector([math.cos(degreesToRadians(cannonXform.rotateAngle)), math.sin(degreesToRadians(cannonXform.rotateAngle)), 0]) ballPos = Vector([-50,0,0]) playSound(fireSound) def explode(): global exploding, explodeTime, ballActive, ballPos playSound(boomSound) exploding = True explodeTime = time.time() ballActive = False ballPos = Vector([-50,0,0]) soundChannels = {} def playSound(sound): if soundChannels.has_key(sound): if soundChannels[sound].get_sound() == sound: return soundChannels[sound] = sound.play() def distanceToTarget(p): min = [35, 0] max = [45, 10] if p[0] >= min[0]: if p[0] <= max[0]: dx = 0 else: dx = p[0] - max[0] else: dx = min[0] - p[0] if p[1] >= min[1]: if p[1] <= max[1]: dy = 0 else: dy = p[1] - max[1] else: dy = min[1] - p[1] return math.sqrt(dx*dx+dy*dy) def update(): global prevTime, ballActive, ballVel, ballPos, exploding t = time.time() dt = t - prevTime prevTime = t if ballActive: ballVel += gravity * dt ballPos += ballVel * dt ballXform.translate = ballPos mountainWidth = 25.0 * (60.0 - ballPos[1])/60.0 if abs(ballPos[0]) < mountainWidth: ballActive = False if distanceToTarget(ballPos) < 2: explode() if exploding: if t - explodeTime > 2: exploding = False glutPostRedisplay() glutInit([]) glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH) glutInitWindowSize(400,400) glutCreateWindow(sys.argv[0]) glutDisplayFunc(draw) glutKeyboardFunc(keyboard) glutSpecialFunc(keyboard) glutIdleFunc(update) glEnable(GL_DEPTH_TEST) quadric = gluNewQuadric() import pygame pygame.mixer.init() fireSound = pygame.mixer.Sound(startDir + 'fire.wav') boomSound = pygame.mixer.Sound(startDir + 'boom.wav') windSound = pygame.mixer.Sound(startDir + 'wind.wav') windSound.set_volume(0.4) windSound.play(-1) glutMainLoop()