Alternativa3d 7 Flying carpet game Part 3 control

David Jones
@david3jones
avatar-davidejones

Now we have the start of our game we need to setup a way for the user to control and interact with the scene. To do this we need to setup a alternativa3d controller. The alternativa3d controller defaults are to move forward,back,left and right using the keyboard and mouse movements. We want to limit the controls to just the mouse having the user moving left and right on screen and maybe a click to shoot a projectile. So to do this we want to take the alternativa3d controller class simpleobjectcontroller and extend it by removing the default functionality and putting in place our own. Here is the code for my custom controller.

package
{
    	import alternativa.engine3d.alternativa3d;
    	import alternativa.engine3d.controllers.SimpleObjectController;
    	import alternativa.engine3d.core.Object3D;
    	import alternativa.engine3d.core.Object3DContainer;
    	import flash.display.InteractiveObject;
    	import flash.events.MouseEvent;
    	import flash.events.KeyboardEvent;
    	use namespace alternativa3d;
    	public class CarpetController extends SimpleObjectController
    	{
    		private var eventSource:InteractiveObject;
    		private var actionBindings:Object;
    		private var thisobject:*;
    		private var leftpress:Boolean = false;
    		private var rightpress:Boolean = false;
    		public function CarpetController(eventSource:InteractiveObject, object:*, speed:Number, speedMultiplier:Number = 3, mouseSensitivity:Number = 1):void
    		{
    			this.eventSource = eventSource;
    			this.thisobject = object;
    			super(eventSource,object,speed,speedMultiplier,mouseSensitivity);
    			this.disable();
    			eventSource.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
    		}
    		private function onMouseMove(e:MouseEvent):void
    		{
    			var mx:Number = this.eventSource.mouseX;
    			var xDist:Number = mx - this.eventSource.stage.stageWidth * 0.5;
    			thisobject.x = -xDist * 0.3;
    			if(thisobject.x < -80) {
    				thisobject.x = -80;
    			}
    			if(thisobject.x > 80) {
    				thisobject.x = 80;
    			}
    			//tilt just the carpet as we move left and right
    			thisobject.getChildAt(1).rotationY = (xDist/50)*Math.PI/180;
    		}
    	}
}

There are a few things to note about this, firstly i’m disabling all of the default functionality by calling this.disable(); the reason i did this was because i had a few problems disabling individual elements but keeping others , so i opted for removing all and putting in place ones i wanted. Secondly you can see i’ve put in the code to handle the mouse movements, i’ve limited this to just small movements and have included the line thisobject.getChildAt(1).rotationY = (xDist/50)*Math.PI/180; which will tilt the carpet slightly as we move in that direction. Now we have our controller we need to set it up in our main class. To do that we need to import it set a variable for it and make sure we call the update function in the on enter frame function.

import CarpetController;
private var controller:CarpetController = new CarpetController(stage, carpetContainer, 200, 3, 0);
private function onEnterFrame(e:Event):void
{
    	//update custom controller
    	controller.update();
}

Here is my full code for the document class, you may notice that the object we are controlling is actually the carpetContainer rather than the camera. The reason for this is that we have the carpet and camera in its own container we have the effect of always being behind the carpet rather than just moving the camera around other objects.

package
{
    	import alternativa.engine3d.core.Camera3D;
    	import alternativa.engine3d.core.Debug;
    	import alternativa.engine3d.core.Object3D;
    	import alternativa.engine3d.core.Object3DContainer;
    	import alternativa.engine3d.core.View;
    	import alternativa.engine3d.materials.FillMaterial;
    	import alternativa.engine3d.materials.TextureMaterial;
    	import alternativa.engine3d.containers.*;
    	import alternativa.engine3d.core.MipMapping;
    	import alternativa.engine3d.primitives.Sphere;
    	import alternativa.engine3d.primitives.Box;
    	import alternativa.engine3d.core.RayIntersectionData;
    	import alternativa.engine3d.core.MouseEvent3D;
    	import flash.display.Sprite;
    	import flash.display.StageAlign;
    	import flash.display.StageScaleMode;
    	import flash.events.Event;
    	import flash.display.BitmapData;
    	import flash.display.Bitmap;
    	import flash.geom.Rectangle;
    	import flash.geom.Point;
    	import flash.geom.Vector3D;
    	import jiglib.geometry.*;
    	import jiglib.physics.*;
    	import jiglib.math.*;
    	import net.glassesfactory.alt3dkit.jiglib.*;
    	import WavePlane;
    	import CarpetController;
    	import DesertSkyBox;
    	[SWF(backgroundColor="#000000", frameRate="100", width="800", height="600")]
    	public class test1 extends Sprite
    	{
    		[Embed(source="carpet.jpg")] static private const Carpet:Class;
    		[Embed(source="terraintex.jpg")] static private const Terraintex:Class;
    		private var rootContainer:Object3DContainer = new Object3DContainer();
    		private var terrainContainer:ConflictContainer = new ConflictContainer();
    		private var carpetContainer:Object3DContainer = new Object3DContainer();
    		private var controller:CarpetController;
    		private var camera:Camera3D;
    		private var terrain:JTerrain;
    		private var physics:GFAlternativa3DPhysics;
    		private var carpet:WavePlane;
    		private var MaterialCarpet:TextureMaterial;
    		private var MaterialTerrain:TextureMaterial;
    		private var sbox:DesertSkyBox;
    		private var changeoverdistance:int = 0;
    		private var pmap2:BitmapData;
    		public function test1():void
    		{
    			//setup stage
    			stage.align = StageAlign.TOP_LEFT;
    			stage.scaleMode = StageScaleMode.NO_SCALE;
    			//setup textures
    			MaterialCarpet = new TextureMaterial(new Carpet().bitmapData,false,true,MipMapping.PER_PIXEL);
    			MaterialTerrain = new TextureMaterial(new Terraintex().bitmapData,false,true,MipMapping.PER_PIXEL);
    			//setup camera
    			camera = new Camera3D();
    			camera.view = new View(stage.stageWidth, stage.stageHeight);
    			addChild(camera.view);
    			addChild(camera.diagram);
    			camera.y = -65;
    			camera.z = 10;
    			camera.lookAt(0,0,0);
    			carpetContainer.addChild(camera);
    			//setup controller
    			controller = new CarpetController(stage, carpetContainer, 200, 3, 0);
    			//setup skybox
    			sbox = new DesertSkyBox(20000);
    			rootContainer.addChild(sbox);
    			//setup physics and terrain
    			physics = new GFAlternativa3DPhysics(terrainContainer, 8);
    			//setup initial terrain
    			setupTerrain();
    			//setup carpet
    			setupCarpet();
    			// Listeners
    			stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
    			stage.addEventListener(Event.RESIZE, onResize);
    		}
    		private function setupCarpet():void
    		{
    			carpetContainer.y = 60;
    			carpetContainer.rotationX = -90*Math.PI/180;
    			carpetContainer.rotationY = -180*Math.PI/180;
    			carpet = new WavePlane(2,40,60,1,36,true,true,true,MaterialCarpet,MaterialCarpet);
    			carpet.z = -20;
    			carpetContainer.addChild(carpet);
    			carpet.scaleX = carpet.scaleY = carpet.scaleZ = 0.5;
    			rootContainer.addChild(carpetContainer);
    		}
    		private function setupTerrain():void
    		{
    			createHeightMap();
    			terrain = physics.createTerrain(pmap2,MaterialTerrain, 500,600,40,11,11);
    			terrain.restitution = 1;
    			GFAlt3dTerrain(terrain.terrainMesh).rotationY = -180*Math.PI/180;
    			GFAlt3dTerrain(terrain.terrainMesh).scaleY = GFAlt3dTerrain(terrain.terrainMesh).scaleX = GFAlt3dTerrain(terrain.terrainMesh).scaleZ = 2;
    			changeoverdistance = 1;
    			rootContainer.addChild(terrainContainer);
    		}
    		private function createHeightMap():void
    		{
    			var pmap:BitmapData = new BitmapData(500, 500);
    			var _seed:uint = Math.round(Math.random()*100);
    			pmap.perlinNoise(500,500, 6, _seed, true, false, 1, true);
    			//copy to a new bitmapdata so we can have a flat area
    			//at the start and end so we can seamlessly join them
    			pmap2 = new BitmapData(500, 600,false,0x000000);
    			var rect:Rectangle = new Rectangle(0, 0, 500, 500);
    			var pt:Point = new Point(0, 50);
    			pmap2.copyPixels(pmap,rect,pt);
    		}
    		private function updateTerrain():void
    		{
    			//add more terrain as we progress forward
    			if(carpetContainer.z >= (changeoverdistance * 1200) - 1500)
    			{
    				terrain = physics.createTerrain(pmap2,MaterialTerrain, 500,600,40,11,11);
    				//GFAlt3dTerrain(terrain.terrainMesh).rotationX = -90*Math.PI/180;
    				GFAlt3dTerrain(terrain.terrainMesh).rotationY = -180*Math.PI/180;
    				GFAlt3dTerrain(terrain.terrainMesh).z = changeoverdistance * 1200;
    				GFAlt3dTerrain(terrain.terrainMesh).scaleY = GFAlt3dTerrain(terrain.terrainMesh).scaleX = GFAlt3dTerrain(terrain.terrainMesh).scaleZ = 2;
    				changeoverdistance++;
    			}
    		}
    		private function onEnterFrame(e:Event):void
    		{
    			//update custom controller
    			controller.update();
    			//always move carpet forward
    			carpetContainer.z += 2;
    			//add new terrain if needed
    			updateTerrain();
    			//integrate jiglib physics
    			physics.engine.integrate(0.1);
    			//render
    			camera.render();
    		}
    		private function onResize(e:Event = null):void {
    			camera.view.width = stage.stageWidth;
    			camera.view.height = stage.stageHeight;
    		}
    		private function randRange(minNum:Number, maxNum:Number):Number
    		{
    			return (Math.floor(Math.random() * (maxNum - minNum + 1)) + minNum);
    		}
    	}
}

carpet You can download the source files here

Downloads

Comments

    Comments are currently closed