PV3DTest20 :敵Cubeに追跡機能を追加
敵Cubeが操作オブジェクトを追跡する機能を追加しました
参考書籍:「14歳からはじめるActionScriptオンラインゲームプログラミング教室」
Qボタンでカメラが操作オブジェクトの真後ろに設定される機能も追加しました
↑モンハンのカメラ機能めざして。。。
★★★ 操作オブジェクトについて :★★★★★★★★★★★★★★★★★★★★★
←↑→↓ボタンで操作オブジェクトを移動させます
← →で方向決定、↑で前進、↓で後退
Zボタンで弾丸発射
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
★★★ 移動状態について :★★★★★★★★★★★★★★★★★★★★★★★★
移動すると手足を動かします
Bボタン押しながら前進・後退で移動速度3倍(手足を動かす速さは変わらず。。。)
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
★★★ カメラについて :★★★★★★★★★★★★★★★★★★★★★★★★★★
W、Sボタンでカメラ位置を上下に変更(カメラのX軸回転を行います)
A、Dボタンで操作オブジェクトを中心にカメラが回転します(カメラのY軸回転を行います)
Aボタンで移動オブジェクトを中心にして左回転、Dボタンでは右回転します
Fボタンで移動オブジェクトからのカメラの距離が変わります
Rボタンでデフォルトのカメラ設定にもどる
Qボタンで操作オブジェクトの背中側の真後ろにカメラを設定
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
/**
* Copyright siouxcitizen ( http://wonderfl.net/user/siouxcitizen )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/3uIG
*/
// forked from hacker_7daxapax's PV3DTest19 :交差判定による弾丸当たり判定
//敵Cubeが操作オブジェクトを追跡する機能を追加しました
//参考書籍:「14歳からはじめるActionScriptオンラインゲームプログラミング教室」
//Qボタンでカメラが操作オブジェクトの真後ろに設定される機能も追加しました
//↑モンハンのカメラ機能めざして。。。
//★★★ 操作オブジェクトについて :★★★★★★★★★★★★★★★★★★★★★
//←↑→↓ボタンで操作オブジェクトを移動させます
//← →で方向決定、↑で前進、↓で後退
//Zボタンで弾丸発射
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
//★★★ 移動状態について :★★★★★★★★★★★★★★★★★★★★★★★★
//移動すると手足を動かします
//Bボタン押しながら前進・後退で移動速度3倍(手足を動かす速さは変わらず。。。)
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
//★★★ カメラについて :★★★★★★★★★★★★★★★★★★★★★★★★★★
//W、Sボタンでカメラ位置を上下に変更(カメラのX軸回転を行います)
//A、Dボタンで操作オブジェクトを中心にカメラが回転します(カメラのY軸回転を行います)
//Aボタンで移動オブジェクトを中心にして左回転、Dボタンでは右回転します
//Fボタンで移動オブジェクトからのカメラの距離が変わります
//Rボタンでデフォルトのカメラ設定にもどる
//Qボタンで操作オブジェクトの背中側の真後ろにカメラを設定
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import org.papervision3d.objects.primitives.Plane;
import org.papervision3d.materials.WireframeMaterial;
import org.papervision3d.materials.ColorMaterial;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.view.Viewport3D;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.render.BasicRenderEngine;
import org.papervision3d.objects.DisplayObject3D;
[SWF(width="500", height="500", frameRate="60", backgroundColor="#111111")]
public class MovieFigure extends Sprite
{
private var container : Sprite;
private var viewport : Viewport3D;
private var scene : Scene3D;
private var camera : Camera3D;
private var wireFramMate : WireframeMaterial;
private var planeObj : Plane;
private var renderer : BasicRenderEngine;
private var planeSize : int = 2000; //Planeオブジェクト1辺の長さ
private var cameraPitch: int = 90; //カメラのX軸回転の値
private var cameraYaw : int = 270; //カメラのY軸回転の値
private var cameraDist : int = -1000; //カメラと操作オブジェクトのキョリ
private var figure00 : Figure; //人型オブジェクト カメラ視点の基準となる
private var enemy01 : Enemy; //攻撃対象敵 青Cube
private var bulletArray : Array = new Array(); //弾丸保持用配列
private const BULLET_NUM : int = 5; //最大弾丸表示数
//MovieFigureクラスのコンストラクタ
public function MovieFigure():void
{
//ビューポート生成
viewport = new Viewport3D(stage.stageWidth, stage.stageHeight);
addChild(viewport);
//シーン生成
scene = new Scene3D();
//レンダリングエンジン生成
renderer = new BasicRenderEngine();
//Planeオブジェクト用ワイヤーフレームマテリアル設定
wireFramMate = new WireframeMaterial(0x0000FF);
//Planeオブジェクト生成
planeObj= new Plane(wireFramMate, planeSize, planeSize, 4, 4);
planeObj.rotationX = 90;
scene.addChild(planeObj);
//Figureオブジェクト生成
figure00 = new Figure(new MaterialsList({all:new ColorMaterial(0xFF0000)}),
new ColorMaterial(0xFF7700),
0,230,-800);
scene.addChild(figure00.body);
//敵Cubeを生成
enemy01 = new Enemy(new MaterialsList({all:new ColorMaterial(0x0000FF)}),800,230,800);
scene.addChild(enemy01.body);
//カメラ設定
camera = new Camera3D();
camera.y = 200;
camera.target = DisplayObject3D.ZERO;
//イベント処理用リスナを設定
stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
}
//フレーム毎の処理
private function onEnterFrame(e:Event):void{
figure00.draw();
enemy01.move(figure00.getPosX(), figure00.getPosZ());
calcBullet();
//カメラ視点設定
setCamera();
renderer.renderScene(scene, camera, viewport);
}
//カメラ視点設定
private function setCamera():void{
//camera.x=-1000*Math.cos((90-body.rotationY)*Math.PI/180)+body.x;
//camera.z=-1000*Math.sin((90-body.rotationY)*Math.PI/180)+body.z;
camera.x=cameraDist*Math.cos((90-figure00.getRotY())*Math.PI/180)+figure00.getPosX();
camera.z=cameraDist*Math.sin((90-figure00.getRotY())*Math.PI/180)+figure00.getPosZ();
camera.target.x=figure00.body.x;
camera.target.y=figure00.body.y;
camera.target.z=figure00.body.z;
camera.orbit(cameraPitch, cameraYaw, true, figure00.body);
}
//キーボードを押したときの処理
//←↑→↓ボタン押下時処理(操作オブジェクト移動のための設定)
//A、D、W、Sボタン押下時処理(カメラ視点変更処理)
//F、Rボタン処理 F:カメラ距離変更 R:カメラ設定デフォルト
//Bボタン処理 Bダッシュを行う
private function onKeyDown(event:KeyboardEvent):void{
//←ボタンDOWN 左回転の設定
if (event.keyCode == 37) {
figure00.leftButtonActioin();
//→ボタンDOWN 右回転の設定
} else if (event.keyCode == 39) {
figure00.rightButtonActioin();
//↑ボタンDOWN 前進の設定
} else if (event.keyCode == 38) {
figure00.upButtonActioin();
//↓ボタンDOWN 後退の設定
} else if (event.keyCode == 40) {
figure00.downButtonActioin();
//Bボタン Bボタン押下中は前進・後退中の移動速度3倍
} else if (event.keyCode == 66) {
figure00.bButtonActioin();
//Zボタン 攻撃用の弾を発射
} else if (event.keyCode == 90) {
attack();
//Aボタン 操作オブジェクトを中心にカメラを左回り回転(Y軸回転)
//4度づつ左回り回転
} else if (event.keyCode == 65) {
cameraYaw = cameraYaw - 4;
if(cameraYaw < 0) {cameraYaw = 360;}
//Dボタン 操作オブジェクトを中心にカメラを右回り回転(Y軸回転)
//4度づつ右回り回転
} else if (event.keyCode == 68) {
cameraYaw = cameraYaw + 4;
if(cameraYaw > 360) {cameraYaw = 0;}
//Wボタン 操作オブジェクトを中心にカメラを上下移動(X軸回転)
} else if (event.keyCode == 87) {
if(cameraPitch > 50) {cameraPitch = cameraPitch - 10;}
//Sボタン 操作オブジェクトを中心にカメラを上下移動(X軸回転)
} else if (event.keyCode == 83) {
if(cameraPitch < 100) {cameraPitch = cameraPitch + 10;}
//Fボタン カメラと操作オブジェクトの距離を変更
} else if (event.keyCode == 70) {
cameraDist += 500;
if(cameraDist > -500) {cameraDist = -1500;}
//Rボタン カメラの設定をデフォルトにもどす
} else if (event.keyCode == 82) {
cameraDist = -1000;
cameraPitch = 90; //カメラのX軸回転の値
cameraYaw = 270; //カメラのY軸回転の値
//Qボタン カメラの操作オブジェクト背中の真後ろに設定
} else if (event.keyCode == 81) {
cameraYaw = 270 - figure00.getRotY();
}
}
//キーボードを離したときの処理
//←↑→↓ボタンリリース時処理(操作オブジェクト移動のための設定解除)
private function onKeyUp(event:KeyboardEvent):void{
//←ボタンUP 左回転の設定設定解除
if (event.keyCode == 37) {
figure00.leftButtonRelease();
//→ボタンUP 右回転の設定設定解除
} else if (event.keyCode == 39) {
figure00.rightButtonRelease();
//↑ボタンUP 前進の設定設定解除
} else if (event.keyCode == 38) {
figure00.upButtonRelease();
//↓ボタンUP 後退の設定設定解除
} else if (event.keyCode == 40) {
figure00.downButtonRelease();
//BボタンUP Bダッシュ解除
} else if (event.keyCode == 66) {
figure00.bButtonRelease();
}
}
//Zボタン押下時に攻撃用の弾丸を発射
private function attack():void{
//Shpereによる攻撃用の弾丸を生成
//画面内に最大5発の弾丸を表示
if (bulletArray.length < BULLET_NUM) {
var bullet : Bullet = new Bullet(
figure00.getRotY(),
figure00.getPosX(),
figure00.getPosZ());
bulletArray.push(bullet);
scene.addChild(bullet.body);
}
}
//発射された弾丸の処理
private function calcBullet():void{
//bulleArray配列内から弾丸をとりだして処理を行う
var bullet : Bullet;
for (var i : int = 0; i < bulletArray.length; i++) {
bullet = bulletArray[i];
bullet.move(); //弾丸の移動処理
//Planeオブジェクトの範囲より外に出た弾丸は削除
if (bullet.boundaryCheck(1000)) {
scene.removeChild(bullet.body);
bulletArray.splice(i,1);
i--;
continue;
}
//弾丸と攻撃対象敵Cubeの当たり判定を行う
//弾丸と衝突した攻撃対象敵Cubeは削除
if (enemy01.isCollision(
bullet.getLeftPosX(),bullet.getRightPosX(),bullet.getFrontPosZ(),bullet.getBackPosZ())) {
scene.removeChild(enemy01.body);
}
}
}
}
}
import flash.display.Sprite;
import org.papervision3d.objects.primitives.Cube;
import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.objects.primitives.Cylinder;
import org.papervision3d.materials.ColorMaterial;
import org.papervision3d.materials.utils.MaterialsList;
//操作オブジェクトを作成
class Figure
{
public var body : Cube; //胴体部
private var head : Sphere; //頭部
private var leftHand : Cylinder; //画面向かって左側手
private var rightHand : Cylinder; //画面向かって右側手
private var leftFoot : Cylinder; //画面向かって左側足
private var rightFoot : Cylinder; //画面向かって右側足
private var materials : MaterialsList;
private var status : int = 0; //操作オブジェクトの表示制御用ステータス
private var rotat : Boolean = false; //Y軸回転判定
private var rotatNum : int = 0; //Y軸回転角度
private var wardMove : Boolean = false; //前進後退判定
private var wardMoveNum : int = 0; //前進後退速度
private var bDash : Boolean = false; //Bダッシュ判定
private var walkDispInterval : int = 0; //歩行表示間隔カウンター
private const INTERVAL: int = 24; //歩行表示間隔
public function Figure(colMateListForBody:MaterialsList,
colMateForLimbs:ColorMaterial,
x:int=0,y:int=230,z:int=0):void {
//操作用人型オブジェクトを作成
//胴体部オブジェクトを親として頭部・手足を子オブジェクトとして加えていく
//胴体部をCubeオブジェクトで作成
body = new Cube(colMateListForBody, 150, 100, 160);
body.x = x;
body.y = y;
body.z = z;
//頭部をSphereでオブジェクト作成
head = new Sphere(colMateForLimbs, 65, 8, 6);
head.y = 150;
body.addChild(head);
//Cylinderオブジェクトで手足を作成
//画面向かって左側の手をCylinderオブジェクトで生成
leftHand = new Cylinder(colMateForLimbs,20,130);
leftHand.x = -110;
leftHand.y = 10;
body.addChild(leftHand);
//画面向かって右側の手をCylinderオブジェクトで生成
rightHand = new Cylinder(colMateForLimbs,20,130);
rightHand.x = 110;
rightHand.y = 10;
body.addChild(rightHand);
//画面向かって左側の足をCylinderオブジェクトで生成
leftFoot = new Cylinder(colMateForLimbs,30,130);
leftFoot.x = -50;
leftFoot.y = -160;
body.addChild(leftFoot);
//画面向かって右側の足をCylinderオブジェクトで生成
rightFoot = new Cylinder(colMateForLimbs,30,130);
rightFoot.x = 50;
rightFoot.y = -160;
body.addChild(rightFoot);
}
//←ボタン押下時処理
public function leftButtonActioin():void {
rotat = true;
rotatNum = -5;
//操作ボタン押下時の値:1を設定
if(walkDispInterval < 1) {
walkDispInterval = 1;
}
}//←ボタンリリース時処理
public function leftButtonRelease():void {
rotat = false;
//操作ボタンリリース時の値:0を設定 他の操作ボタン押下中には設定しない
if(!rotat && !wardMove) {
walkDispInterval = 0;
}
}
//→ボタン押下時処理
public function rightButtonActioin():void {
rotat = true;
rotatNum = 5;
if(walkDispInterval < 1) {
walkDispInterval = 1;
}
}//→ボタンリリース時処理
public function rightButtonRelease():void {
rotat = false;
if(!rotat && !wardMove) {
walkDispInterval = 0;
}
}
//↑ボタン押下時処理
public function upButtonActioin():void {
wardMove = true;
wardMoveNum = 10;
if(walkDispInterval < 1) {
walkDispInterval = 1;
}
}//↑ボタンリリース時処理
public function upButtonRelease():void {
wardMove = false;
if(!rotat && !wardMove) {
walkDispInterval = 0;
}
}
//↓ボタン押下時処理
public function downButtonActioin():void {
wardMove = true;
wardMoveNum = -5;
if(walkDispInterval < 1) {
walkDispInterval = 1;
}
}//↓ボタンリリース時処理
public function downButtonRelease():void {
wardMove = false;
if(!rotat && !wardMove) {
walkDispInterval = 0;
}
}
//Bボタン押下時処理
public function bButtonActioin():void {
bDash = true;
}//Bボタンリリース時処理
public function bButtonRelease():void {
bDash = false;
}
//胴体部の方向情報を返す
public function getRotY():int {
return body.rotationY;
}
//胴体部のX軸位置情報を返す
public function getPosX():int {
return body.x;
}
//胴体部のZ軸位置情報を返す
public function getPosZ():int {
return body.z;
}
//捜査対象オブジェクトの手足表示を制御
private function ctrlWaklDisp():void{
//status:操作オブジェクトの表示制御用ステータス
//0:直立
//1:左手、右足前方&右手、左足後方
//2:左手、右足後方&右手、左足前方
//前進・後退時は1と2の状態を交互に繰り返す
//直立状態(0)からは(1)の状態へ遷移
if (status == 0) {status = 1;}
//(1)の状態をセット後、ステータスを(2)に変更
if (status == 1) {
//左手、右足前方
leftHand.z = 70;
leftHand.rotationX = -40;
rightFoot.z = 50;
rightFoot.rotationX = -30;
//右手、左足後方
rightHand.z = -70;
rightHand.rotationX = 40;
leftFoot.z = -50;
leftFoot.rotationX = 30;
status = 2;
//(2)の状態をセット後、ステータスを(1)に変更
} else if (status == 2) {
//左手、右足後方
leftHand.z = -70;
leftHand.rotationX = 40;
rightFoot.z = -50;
rightFoot.rotationX = 30;
//右手、左足前方
rightHand.z = 70;
rightHand.rotationX = -40;
leftFoot.z = 50;
leftFoot.rotationX = -30;
status = 1;
}
}
public function draw():void {
//← →ボタンが押され続けている間、操作オブジェクトを回転させる
if (rotat) {
body.rotationY += rotatNum;
}
//↑ ↓ボタンが押され続けている間、操作オブジェクトを前進・後退させる
if (wardMove) {
//Bボタンが押されていないときの前進・後退は通常の移動速度
if (!bDash) {
body.moveForward(wardMoveNum);
//Bボタンが押されているときの前進・後退は通常の3倍速
} else {
body.moveForward(wardMoveNum*3);
}
}
//walkDispInterval:
//操作ボタン押下時は1の値、
//操作ボタン押下継続中は1以上の値、
//操作ボタンリリース時は0を設定
//操作ボタンの最初の押下時の歩行表示を行う
if(walkDispInterval == 1) {
//歩行表示
ctrlWaklDisp();
}
//操作ボタン押下継続の間、指定した間隔で歩行表示
if((rotat || wardMove) && walkDispInterval >= 1) {
//いずれかの操作ボタン押下継続時に歩行表示カウンタをカウントアップ
walkDispInterval++;
//指定したインターバルを経過時に歩行表時
if(walkDispInterval > INTERVAL) {
//歩行表示
ctrlWaklDisp();
//歩行表示カウンタを2にもどす(1にもどした場合上記の最初の押下時処理を必ず通り表示がおかしくなるため)
walkDispInterval = 2;
}
}
}
}
import flash.display.Sprite;
import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.materials.ColorMaterial;
//弾丸Sphereを作成
class Bullet
{
public var body : Sphere; //攻撃用の弾丸本体
private var speedX : int = 0; //弾丸X方向速度
private var speedZ : int = 0; //弾丸Z方向速度
private const SPEED : int = 30; //弾丸の速度
private const RADIUS: int = 15; //弾丸本体Sphereの半径
public function Bullet(figRotation:int=0,figX:int=0,figZ:int=0):void {
body = new Sphere(new ColorMaterial(0xFFFF00), RADIUS, 8, 6);
body.x = figX; // 弾丸のX軸の初期値を設定
body.y = 250; // 弾丸のY軸の初期値を設定
body.z = figZ; // 弾丸のZ軸の初期値を設定
// 弾丸速度をX軸の速度成分に分解
speedX = SPEED * Math.cos((90-figRotation)*Math.PI/180);
// 弾丸速度をZ軸の速度成分に分解
speedZ = SPEED * Math.sin((90-figRotation)*Math.PI/180);
}
//X軸とZ軸の速度成分を加算して、X軸とZ軸の移動先の座標を計算
public function move():void {
body.x += speedX;
body.z += speedZ;
}
//弾丸Sphereが画面指定範囲内かチェック
public function boundaryCheck(boundary:int):Boolean {
if(body.x > boundary || body.x < -1*boundary
|| body.z > boundary || body.z < -1*boundary) {
return true;
}
return false;
}
//X軸位置情報を返す
public function getPosX():int {
return body.x;
}
//Z軸位置情報を返す
public function getPosZ():int {
return body.z;
}
//弾丸Sphere左端のX軸位置情報を返す
public function getLeftPosX():int {
return body.x - RADIUS;
}
//弾丸Sphere右端のX軸位置情報を返す
public function getRightPosX():int {
return body.x + RADIUS;
}
//弾丸Sphereの手前側のZ軸位置情報を返す
public function getFrontPosZ():int {
return body.z - RADIUS;
}
//弾丸Sphereの奥側のZ軸位置情報を返す
public function getBackPosZ():int {
return body.z + RADIUS;
}
}
import flash.display.Sprite;
import org.papervision3d.objects.primitives.Cube;
import org.papervision3d.materials.ColorMaterial;
//敵Cubeを作成
class Enemy
{
public var body : Cube; //攻撃対象となる敵本体
private var duration : int = 0 //
private var speedX : int = 0; //敵X方向移動速度
private var speedZ : int = 0; //敵Z方向移動速度
private const SPEED : int = 4; //敵移動速度
private const SIZE: int = 300; //敵本体Cubeのサイズ(縦、横、高さ同じ)
private const DURATION: int = 180; //敵移動先の再計算までの間隔
public function Enemy(colMateList:MaterialsList,
posX:int=0,posY:int=0,posZ:int=0):void {
body = new Cube(colMateList, SIZE, SIZE, SIZE);
body.x = posX; // 敵のX軸の初期値を設定
body.y = posY; // 敵のY軸の初期値を設定
body.z = posZ; // 敵のZ軸の初期値を設定
}
//操作オブジェクトのXとZ軸の座標を元に、敵の移動先を計算
public function move(figX:int,figZ:int):void {
var dist : Number;
if (duration > 0) {
body.x += speedX;
body.z += speedZ;
duration--;
} else {
dist = Math.sqrt(Math.pow(figX-body.x,2)+Math.pow(figZ-body.z,2));
speedX = Math.round((figX-body.x)/dist*SPEED);
speedZ = Math.round((figZ-body.z)/dist*SPEED);
duration = DURATION;
}
}
//敵Cubeが画面指定範囲内かチェック(予定)
public function boundaryCheck(boundary:int):Boolean {
if(body.x > boundary || body.x < -1*boundary
|| body.z > boundary || body.z < -1*boundary) {
return true;
}
return false;
}
//X軸位置情報を返す
public function getPosX():int {
return body.x;
}
//Z軸位置情報を返す
public function getPosZ():int {
return body.z;
}
//敵Cube左端のX軸位置情報を返す
public function getLeftPosX():int {
return body.x - SIZE/2;
}
//敵Cube右端のX軸位置情報を返す
public function getRightPosX():int {
return body.x + SIZE/2;
}
//敵Cubeの手前側のZ軸位置情報を返す
public function getFrontPosZ():int {
return body.z - SIZE/2;
}
//敵Cubeの奥側のZ軸位置情報を返す
public function getBackPosZ():int {
return body.z + SIZE/2;
}
//対象と敵CubeのXZ軸端の座標の交差による当たり判定(交差判定によるあたり判定)
//Y軸は同じ座標にあるものとして判定を行わない
public function isCollision(bulLeftX:int,bulRightX:int,bulFrontZ:int,bulBackZ:int):Boolean {
//交差判定による敵Cubeとの当たり判定計算
if ((getRightPosX() > bulLeftX) && (bulRightX > getLeftPosX())
&& (getBackPosZ() > bulBackZ) && (bulFrontZ > getFrontPosZ())) {
return true;
} else {
return false;
}
}
//対象と敵Cubeの距離で当たり判定(平方根によるあたり判定)
//Y軸は同じ座標にあるものとして判定を行わない
public function isCollisionBySqrt(bulX:int,bulZ:int,compDist:int):Boolean {
//平方根を用いて弾丸と攻撃対象Cubeとの距離を計算
var dist : Number =
Math.sqrt(Math.pow(bulX-getPosX(),2)+Math.pow(bulZ-getPosX(),2));
if (dist > compDist) {
return false;
} else {
return true;
}
}
}