Click for shoot. Press R button to restore glass mesh:
//Bullet Resistant Glass by Mawhrin Skel http://flickr.com/photos/24789570@N03/2698809741/ [Embed(source='2698809741_76eddd085c.jpg')] private var MeshMat:Class; [Embed(source = 'broken.png')] private var BrokenCenter:Class //Parquet 2.0 version 6 by Kochubey http://www.filterforge.com/filters/488.html private const GROUND_TEXTURE:String = "488-v6+.jpg" private const BULLET_TEXTURE:String = "bullet_back.png" private static const BOUNDS:Number = 3000; // Limit for bullet private static const MESH_SIZE:uint = 512 private static const MESH_TESSELATION_X:uint = 8 private static const MESH_TESSELATION_Y:uint = 8 private static const GROUND_Y:int = -300 private static const SHOOT_POWER:Number = 0.15 // 1 is maximum //Glass Mesh private var mesh:Plane; private var meshMaterial:MaterialObject3D private var meshSprite:Sprite private var brokenCenterBmp:Bitmap //Bullet private var bullets:Array = new Array(); private var collidedBulletIndex:uint; //Physics private var isPhysicsOn:Boolean = false private var meshPartsPhysics:Array = new Array() private var detainedParts:Array = new Array() private var detainedPartsCounter:uint = 0 private var ground:Plane public function Main() { super(800, 600, false, false, "CAMERA3D"); preparePv3d(); createMaterials(); createObjects(); addListeners(); } public function preparePv3d():void { addChild(new StatsView(renderer)); } public function createMaterials():void { meshSprite = new Sprite() meshSprite.addChild(new MeshMat() as Bitmap) meshSprite.alpha = 0.3 brokenCenterBmp = new BrokenCenter() as Bitmap brokenCenterBmp.alpha = 0 meshSprite.addChild(brokenCenterBmp); meshMaterial = new MovieMaterial(meshSprite, true, true, false, new Rectangle(0, 0, MESH_SIZE, MESH_SIZE)) meshMaterial.doubleSided = true; } public function createObjects():void { ground = new Plane(new BitmapFileMaterial(GROUND_TEXTURE), 1024, 1024, 6, 6) ground.rotationX = -270 ground.y = GROUND_Y ground.z = 100 scene.addChild(ground) restoreMesh() // create glass mesh } public function breakMesh(mesh:TriangleMesh3D):void { if (!isPhysicsOn && bullets[collidedBulletIndex] !=null) { detainedPartsCounter = 0 detainedParts = new Array() meshPartsPhysics = new Array(); var geom:GeometryObject3D = mesh.geometry; var oTris:Array = geom.faces; var nTris:Array = new Array(); var vert:Vertex3D; var nVert:Vertex3D; var triangle:Triangle3D; var nTriangle:Triangle3D; for (var i:int = 0; i < oTris.length; i++) { var currFace:Triangle3D = oTris[i]; var vertCacheA:Dictionary = new Dictionary(true); var triangleBucketA:Array = new Array(); var vertBucketA:Array = new Array(); var meshX:int var meshY:int triangle = currFace for (var k:int = 0; k < currFace.vertices.length; k++) { vert = currFace.vertices[k]; if(!(nVert = vertCacheA[vert])){ nVert = vert.clone(); vertCacheA[vert] = nVert; } vertBucketA.push(nVert) triangle.vertices[k] = nVert; } // Save position for new mesh meshX = triangle.vertices[0].x meshY = triangle.vertices[0].y // Calculate shift for vertices var shiftX:int = MESH_SIZE/MESH_TESSELATION_X var shiftY:int = MESH_SIZE/MESH_TESSELATION_Y if (triangle.vertices[0].x > triangle.vertices[1].x) shiftX = -MESH_SIZE/MESH_TESSELATION_X if (triangle.vertices[0].y > triangle.vertices[2].y) shiftY = -MESH_SIZE/MESH_TESSELATION_Y // Set local position for vertices triangle.vertices[0].x = 0 triangle.vertices[0].y = 0 triangle.vertices[1].x = shiftX triangle.vertices[1].y = 0 triangle.vertices[2].x = 0 triangle.vertices[2].y = shiftY triangle.updateVertices(); //create new mesh add it on scene var meshA:TriangleMesh3D = new TriangleMesh3D(mesh.material, vertBucketA, [triangle]); meshA.geometry.ready = true meshA.x = meshX meshA.y = meshY brokenCenterBmp.x = bullets[collidedBulletIndex].x - (mesh.x - MESH_SIZE*0.5) -brokenCenterBmp.width/2 brokenCenterBmp.y = -bullets[collidedBulletIndex].y - (mesh.y - MESH_SIZE*0.5) -brokenCenterBmp.height/2 brokenCenterBmp.alpha = 1 //add physics for new mesh meshPartsPhysics.push(new PolygonPhysics(TriangleMesh3D(meshA), 10, .5, 1)); scene.addChild(meshPartsPhysics[i].Object3D); } for each(var meshPart:PolygonPhysics in meshPartsPhysics) { var xdiff : Number = meshPart.Object3D.x-bullets[collidedBulletIndex].x; var ydiff : Number = meshPart.Object3D.y-bullets[collidedBulletIndex].y; var distance : Number = Math.sqrt((xdiff * xdiff) + (ydiff * ydiff)) if (distance > MESH_SIZE*SHOOT_POWER*1.5){ meshPart.isDetained = true; //add impulse for detained parts meshPart.LinImpulse = new Number3D(Math.random()*10, 10, 10-Math.random()*20) meshPart.RotImpulse= new Number3D(Math.random()*.2,Math.random()*.2,Math.random()*.2) }else { //add impulse for not detained parts var impX:int var impY:int if (bullets[collidedBulletIndex].x < meshPart.Object3D.x) impX = MESH_SIZE*SHOOT_POWER*.5 else impX = -MESH_SIZE*SHOOT_POWER*.5 if (bullets[collidedBulletIndex].y < meshPart.Object3D.y) impY = MESH_SIZE*SHOOT_POWER*.5 else impY = -MESH_SIZE*SHOOT_POWER*.5 meshPart.LinImpulse = new Number3D(impX, impY, (MESH_SIZE - distance)*SHOOT_POWER) meshPart.RotImpulse= new Number3D(Math.random()*.6,Math.random()*.6,Math.random()*.6) } } isPhysicsOn = true; } scene.removeChild(mesh) } public function restoreMesh():void { if (meshPartsPhysics.length > 0) { for (var i:int = 0; i < meshPartsPhysics.length; i++) { scene.removeChild(meshPartsPhysics[i].Object3D); } } mesh = new Plane(meshMaterial, MESH_SIZE, MESH_SIZE, MESH_TESSELATION_X, MESH_TESSELATION_Y) scene.addChild(mesh) isPhysicsOn = false brokenCenterBmp.alpha = 0 } public function enterFrameHandler(event:Event):void { if(isPhysicsOn){ updatePhysics(); detainedPartsCounter++ } updateBullet(); rotateCamera(); singleRender(); } private function updateBullet():void { for each(var bullet:DisplayObject3D in bullets) { bullet.moveForward(100); if(bullet.hitTestObject(mesh)){ breakMesh(mesh); collidedBulletIndex = bullets.indexOf(bullet) } if (Math.abs(bullet.x) > BOUNDS/2 || Math.abs(bullet.y) > BOUNDS/2 || Math.abs(bullet.z) > BOUNDS/2) { bullets.splice(bullets.indexOf(bullet), 1 ); scene.removeChild(bullet); } } } private function updatePhysics():void { for (var i:int = 0; i < meshPartsPhysics.length; i++) { if(meshPartsPhysics[i].isDetained == false || detainedPartsCounter > meshPartsPhysics.length*SHOOT_POWER){ if (meshPartsPhysics[i].Object3D.y > GROUND_Y) { meshPartsPhysics[i].AddForce(meshPartsPhysics[i].CGPosition, Number3DPlus.multiply(new Number3D(0, -.2, 0), meshPartsPhysics[i].Mass)); meshPartsPhysics[i].Update(1.7); }else { if(meshPartsPhysics[i].isStopped == false){ meshPartsPhysics[i].resetPos(); meshPartsPhysics[i].Object3D.rotationY = Math.random()*180 // dirty fix meshPartsPhysics[i].ResetImpulse(); meshPartsPhysics[i].ResetForce(); meshPartsPhysics[i].Object3D.y = GROUND_Y meshPartsPhysics[i].Object3D.rotationX = 90 meshPartsPhysics[i].Object3D.rotationZ = 0 meshPartsPhysics[i].isStopped = true } } } } } public function addListeners():void { addEventListener(Event.ENTER_FRAME, enterFrameHandler); stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler); stage.addEventListener(MouseEvent.CLICK, onMouseClick); } private function rotateCamera():void { camera.rotationX = -(viewport.mouseY - stage.height / 2) / 5; camera.rotationY = (viewport.mouseX - stage.width / 2) / 5; } private function onMouseClick(e:MouseEvent):void { var bullet:Plane = new Plane(new BitmapFileMaterial(BULLET_TEXTURE), 64, 64, 1, 1) bullet.copyPosition(camera); bullet.copyTransform(camera); bullet.moveForward(400); scene.addChild(bullet); bullets.push(bullet); } public function keyUpHandler(e:KeyboardEvent):void { if (isChar(e.charCode, "r")) { if (meshPartsPhysics.length > 0) restoreMesh(); else breakMesh(mesh); } } private function isChar(code:Number, str:String):Boolean{ if(code == str.charCodeAt()) return true; return false; }
07.10.2008. 21:10
This article hasn't been commented yet.
Write a comment
* = required field