Example: Shooter
February 20, 2008 – 1:02 pmClick to shoot. W, A, S, D or Arrow Keys to move. In the next example I’ll cover how to check if your bullet hit another object.
[source:javascript]
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.ui.Keyboard;
import flash.ui.Mouse;
import org.papervision3d.cameras.FreeCamera3D;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.materials.WireframeMaterial;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.Cube;
import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.render.BasicRenderEngine;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.view.Viewport3D;
[SWF(width="640", height="480", backgroundColor="0x000000", frameRate="31")]
public class Shooter extends Sprite {
private var viewport:Viewport3D;
private var scene:Scene3D;
private var camera:FreeCamera3D;
private var renderer:BasicRenderEngine;
public var inertia:Number = 3;
public var movementFactor:Number = 100;
private var keyRight:Boolean = false;
private var keyLeft:Boolean = false;
private var keyForward:Boolean = false;
private var keyBackward:Boolean = false;
private var forwardFactor:Number = 0;
private var sideFactor:Number = 0;
private const BOUNDS:Number = 50000;
private var bullets:Array;
public function Shooter() {
pv3d();
setupScene();
addEventListeners();
}
private function pv3d():void {
viewport = new Viewport3D();
addChild(viewport);
scene = new Scene3D();
camera = new FreeCamera3D();
renderer = new BasicRenderEngine();
}
private function setupScene():void {
bullets = new Array();
var materialsList:MaterialsList = new MaterialsList();
materialsList.addMaterial(new WireframeMaterial(0×003300), “all”);
var insideTheBox:Cube = new Cube(materialsList, BOUNDS, BOUNDS, BOUNDS, 10, 10, 10, Cube.ALL);
scene.addChild(insideTheBox);
Mouse.hide();
}
private function addEventListeners():void {
stage.addEventListener(MouseEvent.CLICK, onMouseClick);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onMouseClick(e:MouseEvent):void {
var bullet:Sphere = new Sphere(new WireframeMaterial(0xcc0000), 50);
bullet.copyPosition(camera);
bullet.copyTransform(camera);
bullet.moveForward(400);
scene.addChild(bullet);
bullets.push(bullet);
}
private function onKeyDown(e:KeyboardEvent):void {
switch( e.keyCode ) {
case “W”.charCodeAt():
case Keyboard.UP:
keyForward = true;
keyBackward = false;
break;
case “S”.charCodeAt():
case Keyboard.DOWN:
keyBackward = true;
keyForward = false;
break;
case “A”.charCodeAt():
case Keyboard.LEFT:
keyLeft = true;
keyRight = false;
break;
case “D”.charCodeAt():
case Keyboard.RIGHT:
keyRight = true;
keyLeft = false;
break;
}
}
private function onKeyUp(e:KeyboardEvent):void
{
switch( e.keyCode ){
case “W”.charCodeAt():
case Keyboard.UP:
keyForward = false;
break;
case “S”.charCodeAt():
case Keyboard.DOWN:
keyBackward = false;
break;
case “A”.charCodeAt():
case Keyboard.LEFT:
keyLeft = false;
break;
case “D”.charCodeAt():
case Keyboard.RIGHT:
keyRight = false;
break;
}
}
private function onEnterFrame(e:Event):void {
for each(var bullet:DisplayObject3D in bullets) {
bullet.moveForward(100);
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);
}
}
if(keyForward){
forwardFactor += 50;
}
if(keyBackward){
forwardFactor += -50;
}
if(keyLeft){
sideFactor += -50;
}
if(keyRight){
sideFactor += 50;
}
forwardFactor +=( 0-forwardFactor ) / inertia;
sideFactor += ( 0 - sideFactor ) / inertia;
if (forwardFactor > 0){
camera.moveForward( forwardFactor );
}else{
camera.moveBackward( -forwardFactor );
}
if (sideFactor > 0){
camera.moveRight( sideFactor );
}else{
camera.moveLeft( -sideFactor );
}
camera.rotationX = -(viewport.mouseY - stage.height / 2) / 5;
camera.rotationY = (viewport.mouseX - stage.width / 2) / 5;
renderer.renderScene(scene, camera, viewport);
}
}
}
[/source]

18 Responses to “Example: Shooter”
Very nice, great example.
By Martin on Feb 20, 2008
well there is a little problem with that … since your mouse is not always in the center. Like you cannot make a 360 degrees turn or even 180 …
By fassa on Feb 21, 2008
@fassa- I purposefully restricted the camera movement to keep the user oriented. Feel free to modify the code to meet your personal demands.
By John Lindquist on Feb 21, 2008
for example is there a way to set the mouse in the middle in an enter frame handler and determine the direction it moved to move the camera ?
By fassa on Feb 21, 2008
ahh well then how can you make it move exactly like in a 1st person shooter ?
By fassa on Feb 21, 2008
I’ll cover that later. Today’s a busy day.
By John Lindquist on Feb 21, 2008
I’ll be happy to see it
and i will test it for sure
My actual point is to create a nice 3d model explorer where you can swich fixed cameras and have a free roam camera to wander around to see if your models are ok.
By fassa on Feb 23, 2008
This seems to be pretty cpu intensive, even when there are no bullets. Is there any particular reason for that?
By Richard on Feb 25, 2008
Hello i was wondering where you have got the render and viewport classes as i cant find them and you seem to have them in your papervision package, what gives?
By Spazy T on Feb 27, 2008
Hi!
You need GratWhite version to have those classes, but is not working ether because some error in those classes!
So I don’t know how he made it to work!
By george on Mar 6, 2008
“This seems to be pretty cpu intensive….”
Because the giant cube that you are inside is alot of polygons and papervision uses software rendering. I made a Wolf3d demo where I load map 1 of the Wolf3d shareware version and just place a cube where each wall exists, and you can barely move in the thing after that just because of the cubes being there.
By rey on Mar 14, 2008
This seems to be pretty cpu intensive….
Yeah is real slow when I run it in flash dev
but pretty cool never the less
By Nikos on Mar 22, 2008
Ive been play with this for ages, is a great laugh changing everything
By Nikos on Mar 22, 2008
here my version
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.ui.Keyboard;
import flash.ui.Mouse;
import org.papervision3d.cameras.FreeCamera3D;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.materials.WireframeMaterial;
import org.papervision3d.materials.ColorMaterial;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.Cube;
import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.render.BasicRenderEngine;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.view.Viewport3D;
import org.papervision3d.objects.primitives.Cone;
import org.papervision3d.materials.BitmapFileMaterial;
public class Shooter extends Sprite {
private var viewport:Viewport3D;
private var scene:Scene3D;
private var camera:FreeCamera3D;
private var renderer:BasicRenderEngine;
public var inertia:Number = 3;
public var movementFactor:Number = 100;
private var keyRight:Boolean = false;
private var keyLeft:Boolean = false;
private var keyForward:Boolean = false;
private var keyBackward:Boolean = false;
private var forwardFactor:Number = 0;
private var sideFactor:Number = 0;
private var ballCount = 0;
private const BIG_BALL_COUNT:Number = 5;
private const HUGE_BALL_COUNT:Number = 10;
private const BOUNDSX:Number = 500000;
private const BOUNDSY:Number = 500000;
private const BOUNDSZ:Number = 500000;
private var bullets:Array;
public function Shooter() {
pv3d();
setupScene();
addEventListeners();
}
private function pv3d():void {
viewport = new Viewport3D();
addChild(viewport);
scene = new Scene3D();
camera = new FreeCamera3D();
renderer = new BasicRenderEngine();
}
private function setupScene():void {
bullets = new Array();
var materialsList:MaterialsList = new MaterialsList();
materialsList.addMaterial(new WireframeMaterial(0×00FF00), “all”);
var insideTheBox:Cube = new Cube(materialsList, BOUNDSX, BOUNDSY, BOUNDSZ, 10, 10, 10, Cube.ALL);
scene.addChild(insideTheBox);
Mouse.hide();
}
private function addEventListeners():void {
stage.addEventListener(MouseEvent.CLICK, onMouseClick);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onMouseClick(e:MouseEvent):void {
var cone:Cone = new Cone(new BitmapFileMaterial(”http://papervision2.com/wp-content/downloads/ourtex.jpg”), 200, 2000);
// I’ve added a width and height to change the shape of my cone.
cone.scale = 3;
cone.copyPosition(camera);
cone.copyTransform(camera);
cone.moveLeft(20);
cone.yaw(20);
// Here, I’ve made my cone spin faster by increasing the amount sent to yaw();
var bullet;
if(ballCount BOUNDS/2 || Math.abs(bullet.y) > BOUNDS/2 || Math.abs(bullet.z) > BOUNDS/2) {
// bullets.splice(bullets.indexOf(bullet), 1 );
// scene.removeChild(bullet);
// }
}
if(keyForward){
forwardFactor += 5000;
}
if(keyBackward){
forwardFactor += -5000;
}
if(keyLeft){
sideFactor += -5000;
}
if(keyRight){
sideFactor += 5000;
}
forwardFactor +=( 0-forwardFactor ) / inertia;
sideFactor += ( 0 - sideFactor ) / inertia;
if (forwardFactor > 0){
camera.moveForward( forwardFactor );
}else{
camera.moveBackward( -forwardFactor );
}
if (sideFactor > 0){
camera.moveRight( sideFactor );
}else{
camera.moveLeft( -sideFactor );
}
camera.rotationX = -(viewport.mouseY - stage.height )/1.5 ;
camera.rotationY = (viewport.mouseX - stage.width )/1.5 ;
renderer.renderScene(scene, camera, viewport);
}
}
}
By Nikos on Mar 25, 2008
hmm my last post cut out half my code:(
By Nikos on Mar 25, 2008
i’ve a problem. i’ve created a cube with 1024 width, 500 depth and 600 in height.all are working but when tested in flash it is not the same with the stage size i.e 1024×600. i want to make the completely viewable not bound to anything.how to work around this? thanks
By hud on Apr 18, 2008
nvm, i found the solution that i wanted. thanks
By hud on Apr 18, 2008
Maybe this is of some use to anyone.
I changed the code so you can spin around as you like. Also movement is restricted to x and z
Code is also optimized for Flash CS3
I used a bit of code from another tutorial for the ground. A bit messy code, but it’s working.
Have fun y’all.
package base{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.ui.Keyboard;
import flash.ui.Mouse;
import org.papervision3d.cameras.FreeCamera3D;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.materials.WireframeMaterial;
import org.papervision3d.materials.BitmapFileMaterial;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.Plane;
import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.render.BasicRenderEngine;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.view.Viewport3D;
[SWF(width="640", height="480", backgroundColor="0x000000", frameRate="31")]
public class Shooter extends Sprite {
private var viewport:Viewport3D;
private var scene:Scene3D;
private var camera:FreeCamera3D;
private var renderer:BasicRenderEngine;
public var inertia:Number = 3;
public var movementFactor:Number = 100;
private var keyRight:Boolean = false;
private var keyLeft:Boolean = false;
private var keyForward:Boolean = false;
private var keyBackward:Boolean = false;
private var forwardFactor:Number = 0;
private var sideFactor:Number = 0;
private var toneel:Object = new Object();
private var oudeMuisX = 0;
private var verplaatsing = 0;
private var rotatie = 0;
private const BOUNDS:Number = 50000;
private var bullets:Array;
public function Shooter($root) {
toneel = $root;
pv3d();
setupScene();
addEventListeners();
}
private function pv3d():void {
viewport = new Viewport3D();
toneel.addChild(viewport);
scene = new Scene3D();
camera = new FreeCamera3D(1, 500);
camera.moveUp(300);
renderer = new BasicRenderEngine();
}
private function setupScene():void {
bullets = new Array();
var materialsList:MaterialsList = new MaterialsList();
materialsList.addMaterial(new WireframeMaterial(0×003300), “all”);
for (var x:Number = 0; x <4; x++) {
for (var y:Number = 0; y BOUNDS/2 || Math.abs(bullet.y) > BOUNDS/2 || Math.abs(bullet.z) > BOUNDS/2) {
bullets.splice(bullets.indexOf(bullet), 1 );
scene.removeChild(bullet);
}
}
if(keyForward){
forwardFactor += 50;
}
if(keyBackward){
forwardFactor += -50;
}
if(keyLeft){
sideFactor += -50;
}
if(keyRight){
sideFactor += 50;
}
forwardFactor +=( 0-forwardFactor ) / inertia;
sideFactor += ( 0 - sideFactor ) / inertia;
var radians = camera.rotationY * Math.PI/180;
camera.x = camera.x + int(Math.sin(radians) * forwardFactor);
camera.z = camera.z + int(Math.cos(radians) * forwardFactor);
radians = (camera.rotationY + 90) * Math.PI/180;
camera.x = camera.x + int(Math.sin(radians) * sideFactor);
camera.z = camera.z + int(Math.cos(radians) * sideFactor);
//toneel.tekst.text = camera.rotationY;
if(viewport.mouseX > 20 && viewport.mouseX < 530){
verplaatsing = (viewport.mouseX - oudeMuisX) / 2;
}
camera.rotationY = camera.rotationY + verplaatsing;
camera.rotationX = -(viewport.mouseY - toneel.stage.height / 2) / 5;
oudeMuisX = viewport.mouseX;
//*************************************
renderer.renderScene(scene, camera, viewport);
}
}
}
By Hans on Jun 8, 2008