(C)WorldWideSoftware
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>弾の軌跡3</title>
</head>
<body>
<a href="http://www.wwsft.com">(C)WorldWideSoftware</a><br>
<canvas id="bg" width="640" height="640"></canvas><br>
画面クリック(タップ)した位置からレーザー発射<br>
フレームごとのレーザーの軌跡(座標)を保持し、新しいものほど明るく(古いものほど暗く)描画することで、レーザーっぽく見せています<br>
<a href="laser02src.html">ソースコードの確認</a>
<script>
//描画面(キャンバス)の準備
var cvs = document.getElementById("bg");
var ctx = cvs.getContext("2d");
//マウスとタップの判定
var tapX = 320, tapY = 320, tapC = 0;
cvs.addEventListener("touchstart", touchStart);
cvs.addEventListener("touchend", touchEnd);
function touchStart(ev) {
ev.preventDefault();
var rect = ev.target.getBoundingClientRect();
tapX = ev.touches[0].clientX-rect.left;
tapY = ev.touches[0].clientY-rect.top;
tapC = 1;
}
function touchEnd(ev) { tapC = 0; }
cvs.addEventListener("mousedown", mouseDown);
cvs.addEventListener("mouseup", mouseUp);
function mouseDown(ev) {
var rect = ev.target.getBoundingClientRect();
tapX = ev.clientX-rect.left;
tapY = ev.clientY-rect.top;
tapC = 1;
}
function mouseUp(ev) { tapC = 0; }
//レーザー到達地点
var targetX = 0;
var targetY = 80;
//レーザー用の変数 今回は3本セットで処理しています
var LASER_NUM = 3;
var LASER_MAX = 100;//レーザーの軌跡を管理
var laserP = 0;//発射用のフラグ
var laX = [0,0,0], laY = [0,0,0];//座標
var laXP = [0,0,0], laYP = [0,0,0];//方向(移動量)
var laPP = [0,0,0];//発射後のカウント
//レーザーの軌跡を管理するための二次元配列
var laCX = [], laCY = [];//軌跡の座標
var laCC = [];//軌跡の色(描画時アルファ値に変換)
for(var n = 0; n<LASER_NUM; n++) {
laCX[n] = [];
laCY[n] = [];
laCC[n] = [];
for(var m=0; m<LASER_MAX; m++) {
laCX[n][m] = 0;
laCY[n][m] = 0;
laCC[n][m] = 0;
}
}
//レーザーをセット(自機から撃ち出す処理)
function setLaser() {
for(var n=0; n<LASER_NUM; n++) {
laX[n] = tapX;
laY[n] = tapY;
laXP[n] = (n-(LASER_NUM-1)/2)*(160/LASER_NUM);
laYP[n] = 24;//←↑レーザーの方向、初期値は後方左右に広げて撃ち出す
laPP[n] = 0;
for(var m=0; m<LASER_MAX; m++) laCC[n][m] = 0;
}
laserP = 90;//次のレーザーが撃てるまでのフレーム数
}
//線を引く関数
ctx.lineCap = "round";
function line(x1, y1, x2, y2, wid, col) {
ctx.lineWidth = wid;
ctx.strokeStyle = col;
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
}
//距離を求める関数
function getDis(x1, y1, x2, y2) {
return( Math.sqrt( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) ) );
}
//メイン処理
function mainProc() {
var c, m, n, dis, dx, dy;
ctx.fillStyle = "black";
ctx.fillRect(0, 0, 640, 640);
//ターゲットの位置
targetX++; if(targetX > 640) targetX = 0;
line(targetX-20,targetY,targetX+20,targetY,12,"#c00000");
line(targetX,targetY-20,targetX,targetY+20,12,"#c00000");
//レーザー発射?
if(laserP == 0) {
if(tapC > 0) setLaser();
}
else {
laserP--;
}
//レーザーの移動と描画
for(n=0; n<LASER_NUM; n++) {
if(laX[n]!=0 || laY[n]!=0) {//発射されている
//レーザーの座標を保持 → これがレーザーの軌跡となる
laCX[n][laPP[n]] = laX[n];
laCY[n][laPP[n]] = laY[n];
laCC[n][laPP[n]] = 100;
if(laPP[n] < LASER_MAX-1) laPP[n]++;//発射後のカウント
//レーザーが向かう方向(座標の変化量)を計算
dis = getDis(targetX, targetY, laX[n], laY[n]);//ターゲットとの距離
if(dis < 1) dis = 1;
dx = 20*(targetX-laX[n])/dis;//ターゲットに向かうX方向ベクトル n倍してX方向最大速度
dy = 20*(targetY-laY[n])/dis;//ターゲットに向かうY方向ベクトル n倍してY方向最大速度
laXP[n] = (laXP[n]*8+dx*2)/10;
laYP[n] = (laYP[n]*8+dy*2)/10;
laX[n] += laXP[n];//座標の計算
laY[n] += laYP[n];
if(getDis(targetX, targetY, laX[n], laY[n]) < 20) { laX[n]=0; laY[n]=0; };//ターゲットに到達
if(laserP == 0) { laX[n]=0; laY[n]=0; };//あるいは一定時間経過したらレーザーを消滅させる
}
//レーザーの軌跡を描く
for(c=0; c<4; c++) {//4色重ねてレーザーっぽく
for(m=1; m<laPP[n]; m++) {
if(laCC[n][m] > 0) {
line(laCX[n][m-1], laCY[n][m-1], laCX[n][m], laCY[n][m], 16-c*4, "rgba("+(c*40)+","+(c*80)+","+(255)+","+(laCC[n][m]/100)+")");
laCC[n][m]--;
}
}
}
}
//タップ位置の表示
ctx.fillStyle = "white";
ctx.fillText(laserP, tapX, tapY);
setTimeout(mainProc, 1000/60);//リアルタイム処理
}
mainProc();//処理スタート
</script>
</body>
</html>
←動作確認に戻る