子供のころ、PCのフリーセル とピンボール が大好きでした。
フリーセル は最後にシャーッてなるのがいいんですよね。あのシャーッてやつをJavascript で再現していきます。
ちなみに昔と違って、今のWindows はストアからフリーセル をインストールする必要があるみたいですね。
www.microsoft.com
今でもシャーやってくれるみたいです。
と、思ったら別のアニメーションも用意されてました。
このアニメーションをJSで組んでみる このトランプがシャーッてなるやつをいつでも見れるようにJavaScript で組んでいきたいと思います。
・
・
2日後
・
・
微調整こだわり過ぎて2日掛かってました。
作ったスクリプト 全体は以下の通りです。
コード全体
< script >
let imageWidth = 409
let imageHeight = 600
data = new Array (
"https://3.bp.blogspot.com/-x1YD4kp-X9E/WQBAA3RKDbI/AAAAAAABD9M/5K8vEH6kYSo5M9r2jzxheGlnup2k-El5gCLcB/s800/card_heart_02.png" ,
"https://2.bp.blogspot.com/-S-31SRfkS1o/WQBAEtCo1nI/AAAAAAABD98/fzjjCIIibhMkeoKx9NfyTo3i1TjRaONPQCLcB/s800/card_spade_01.png" ,
"https://4.bp.blogspot.com/-hIKME4x_kbQ/WQA_3IHzulI/AAAAAAABD7o/Ft4JOq2ydaEHteja59Zzv_i3ieXnmONwwCLcB/s800/card_club_03.png" ,
"https://4.bp.blogspot.com/-WNnDDDnVkrs/WQA_9vUTTJI/AAAAAAABD8g/PSyYSizOnVkaC37L7bLn82Ex83Tvm0BKACLcB/s800/card_diamond_04.png" ,
"https://4.bp.blogspot.com/-bvSGYORb6Xg/WQBAF61kUOI/AAAAAAABD-Q/SalVkKKYYt85TNJJsOjmgNwfT0ao3foewCLcB/s800/card_spade_05.png" ,
"https://3.bp.blogspot.com/-w5tuOxBszlU/WQBABseF49I/AAAAAAABD9c/9yF8y-6012MKF5UlSz-dxORnZU_YhEuxgCLcB/s800/card_heart_06.png" ,
"https://2.bp.blogspot.com/-LXJw0prlZp0/WQA_6wZyEVI/AAAAAAABD74/eFWVHzCtgLMj_C-JPzjOd7YfhiveHytlQCLcB/s800/card_club_07.png" ,
"https://1.bp.blogspot.com/-FZGbdtedARU/WQA__nBH5iI/AAAAAAABD84/X9BsjJbBLZcuGBr5VT2EeisGjlp0wtJpwCLcB/s800/card_diamond_08.png" ,
"https://1.bp.blogspot.com/-lYcdLoEoqhk/WQBAGkz_02I/AAAAAAABD-Y/BzeTL07VRhc9viqmclMywil_LqOdQGL5QCLcB/s800/card_spade_09.png" ,
"https://4.bp.blogspot.com/-Dj2Yzi1XR-E/WQBADWUni-I/AAAAAAABD9s/2Cy3plnNZGwt9sV3vDO4eCvJSSg9DGx-wCLcB/s800/card_heart_10.png"
)
imag= new Array () ;
for ( i= 0 ; i< data. length; i++ ){
imag[ i] = new Image () ;
imag[ i] . src = data[ i] ;
}
var canvas = document . querySelector ( "canvas" ) ;
var context = canvas. getContext ( '2d' ) ;
var canvas = document . getElementById ( "canvas" ) ;
canvas. width = canvas. clientWidth;
canvas. height = canvas. clientHeight;
var Card = function ( scale, color, vx, vxs, vy, gv) {
this. scale = scale;
this. dstWidth = dstWidth;
this. dstHeight = dstHeight;
this. kind = kind;
this. vx = vx;
this. vxs = vxs;
this. vy = vy;
this. gv = gv;
this. position = {
x : 0 ,
y : 0
} ;
} ;
var Cards = [] ;
var kind;
var scale;
var dstWidth;
var dstHeight;
var x;
var xs;
var y;
var g;
var indx;
var startDate = new Date () ;
var interval = 2000 ;
function animloop (){
requestAnimFrame ( animloop) ;
if ( new Date () - startDate > interval){
startDate = new Date () ;
kind = Math . random () * 10 ;
scale = Math . random () * ( 0 . 25 - 0 . 1 ) + 0 . 1 ;
dstWidth = imageWidth * scale;
dstHeight = imageHeight * scale;
x = Math . random () * ( 10 ) - 5 ;
xs = x / 10 ;
y = Math . random () * 9 + 4 ;
g = Math . random () * 0 . 2 + 0 . 3 ;
indx = Cards. length;
Cards[ indx] = new Card ( scale, kind, x, xs, - y, g) ;
Cards[ indx] . position. x = Math . random () * ( canvas. width) ;
Cards[ indx] . position. y = 100 ;
}
for ( var i in Cards) {
Cards[ i] . update () ;
}
}
window . requestAnimFrame = ( function (){
return window . requestAnimationFrame ||
window . webkitRequestAnimationFrame ||
window . mozRequestAnimationFrame ||
function ( callback ){
window . setTimeout ( callback, 1000 / 60 ) ;
} ;
})() ;
Card. prototype. update = function () {
this. vy += this. gv;
this. position. x += this. vx;
this. position. y += this. vy;
if ( this. position. y > canvas. height - this. dstHeight) {
this. vy *= -0 . 8 ;
this. vx *= 0 . 85 ;
this. position. y = canvas. height - this. dstHeight;
if ( Math . abs ( this. vx) < 0 . 8 ){
this. position. x += this. vxs;
}
}
this. draw () ;
} ;
Card. prototype. draw = function () {
context. beginPath () ;
context. arc ( this. position. x, this. position. y, this. scale, 0 , 2 * Math . PI, false ) ;
context. fillStyle = this. color;
console . log ( Math . floor ( this. kind))
context. drawImage ( imag[ Math . floor ( this. kind)] , this. position. x, this. position. y, this. dstWidth, this. dstHeight) ;
} ;
animloop () ;
</ script >
画像読み込み まず、冒頭で画像の読み込み等をしてます。(
いらすとや からお借りしてます)
let imageWidth = 409
let imageHeight = 600
data = new Array (
"https://3.bp.blogspot.com/-x1YD4kp-X9E/WQBAA3RKDbI/AAAAAAABD9M/5K8vEH6kYSo5M9r2jzxheGlnup2k-El5gCLcB/s800/card_heart_02.png" ,
"https://2.bp.blogspot.com/-S-31SRfkS1o/WQBAEtCo1nI/AAAAAAABD98/fzjjCIIibhMkeoKx9NfyTo3i1TjRaONPQCLcB/s800/card_spade_01.png" ,
"https://4.bp.blogspot.com/-hIKME4x_kbQ/WQA_3IHzulI/AAAAAAABD7o/Ft4JOq2ydaEHteja59Zzv_i3ieXnmONwwCLcB/s800/card_club_03.png" ,
"https://4.bp.blogspot.com/-WNnDDDnVkrs/WQA_9vUTTJI/AAAAAAABD8g/PSyYSizOnVkaC37L7bLn82Ex83Tvm0BKACLcB/s800/card_diamond_04.png" ,
"https://4.bp.blogspot.com/-bvSGYORb6Xg/WQBAF61kUOI/AAAAAAABD-Q/SalVkKKYYt85TNJJsOjmgNwfT0ao3foewCLcB/s800/card_spade_05.png" ,
"https://3.bp.blogspot.com/-w5tuOxBszlU/WQBABseF49I/AAAAAAABD9c/9yF8y-6012MKF5UlSz-dxORnZU_YhEuxgCLcB/s800/card_heart_06.png" ,
"https://2.bp.blogspot.com/-LXJw0prlZp0/WQA_6wZyEVI/AAAAAAABD74/eFWVHzCtgLMj_C-JPzjOd7YfhiveHytlQCLcB/s800/card_club_07.png" ,
"https://1.bp.blogspot.com/-FZGbdtedARU/WQA__nBH5iI/AAAAAAABD84/X9BsjJbBLZcuGBr5VT2EeisGjlp0wtJpwCLcB/s800/card_diamond_08.png" ,
"https://1.bp.blogspot.com/-lYcdLoEoqhk/WQBAGkz_02I/AAAAAAABD-Y/BzeTL07VRhc9viqmclMywil_LqOdQGL5QCLcB/s800/card_spade_09.png" ,
"https://4.bp.blogspot.com/-Dj2Yzi1XR-E/WQBADWUni-I/AAAAAAABD9s/2Cy3plnNZGwt9sV3vDO4eCvJSSg9DGx-wCLcB/s800/card_heart_10.png"
)
imag= new Array () ;
for ( i= 0 ; i< data. length; i++ ){
imag[ i] = new Image () ;
imag[ i] . src = data[ i] ;
}
var canvas = document . querySelector ( "canvas" ) ;
var context = canvas. getContext ( '2d' ) ;
クラスの定義 ここはクラスを定義しています。
var Card = function ( scale, color, vx, vxs, vy, gv) {
this. scale = scale;
this. dstWidth = dstWidth;
this. dstHeight = dstHeight;
this. kind = kind;
this. vx = vx;
this. vxs = vxs;
this. vy = vy;
this. gv = gv;
this. position = {
x : 0 ,
y : 0
} ;
} ;
メインのループ処理 ここはメインのループ処理です。
function animloop (){
requestAnimFrame ( animloop) ;
if ( new Date () - startDate > interval){
startDate = new Date () ;
kind = Math . random () * 10 ;
scale = Math . random () * ( 0 . 25 - 0 . 1 ) + 0 . 1 ;
dstWidth = imageWidth * scale;
dstHeight = imageHeight * scale;
x = Math . random () * ( 10 ) - 5 ;
xs = x / 10 ;
y = Math . random () * 9 + 4 ;
g = Math . random () * 0 . 2 + 0 . 3 ;
indx = Cards. length;
Cards[ indx] = new Card ( scale, kind, x, xs, - y, g) ;
Cards[ indx] . position. x = Math . random () * ( canvas. width) ;
Cards[ indx] . position. y = 100 ;
}
for ( var i in Cards) {
Cards[ i] . update () ;
}
}
この部分でクラス追加の制御をしてます。
if ( new Date () - startDate > interval){
startDate = new Date () ; </ code>
今回はvar interval = 2000;
に設定しているので2秒間隔ですね。
クラスの更新 Cards[i].update();
で以下の処理を呼び出してます。
Card. prototype. update = function () {
this. vy += this. gv;
this. position. x += this. vx;
this. position. y += this. vy;
if ( this. position. y > canvas. height - this. dstHeight) {
this. vy *= -0 . 8 ;
this. vx *= 0 . 85 ;
this. position. y = canvas. height - this. dstHeight;
if ( Math . abs ( this. vx) < 0 . 8 ){
this. position. x += this. vxs;
}
}
this. draw () ;
} ;
地面に衝突する(y座標がcanvas の大きさに達する)と、y軸の速度[vy]をマイナスにすることでトランプを上に描画しています。
x軸の速度が絶対値で0.8以下となった際は、これ以上バウンドしないと判断し、生成時の速度×0.1で等速に動かしています。
動かしてみた 動かしてみると、こんな感じです。
VIDEO youtu.be
以下リンクよりブラウザでお試しいただけます。
https://castoroides.github.io/others/Freecell_fall.html