Alternativa3d 7 Flying carpet game Part 3 control
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);
}
}
}
Comments
Comments are currently closed