ルール
ルーレット(roulette)は、回転する円盤に球を投げ入れ、落ちる場所を当てるカジノゲーム。
確率の低い賭け方ほど配当金が高い。
インサイド・ベット
- Straight-Up(ストレート・アップ): 数字1点賭け
- Split Bet(スプリット・ベット): 2点賭け
- Street Bet(ストリート・ベット): 3点賭け
- Corner Bet(コーナー・ベット): 4点賭け
- Double Street Bet(ダブル・ストリート・ベット): 6点賭け
- Four Numbers bet(フォー・ナンバー・ベット): 4点賭け
アウトサイド・ベット
- Dozen Bet(ダズン・ベット): 4列12点賭け
- Column Bet(カラム・ベット): 1行12点賭け
- Red-Black(レッド・ブラック): 赤黒
- High-Low(ハイ・ロウ): 大小
- Odd-Even(オッド・イーブン)奇数・偶数
view source
JavaScript
document.title = 'ルーレットで遊ぶ カジノゲーム';
$(function(){
$demo = $('#demo');
var w = window.innerWidth;
var h = window.innerHeight;
w = Math.min(w,h) - 80;
var c = w/2;
var t=0;
var deg = 0;
var ballDeg = 0;
var speed = 0;
var ballSpeed = 0;
var se = new Audio('/mp3/pi.mp3');
var sePach = new Audio('pachipachi.mp3');
se.volume = 0.1;
//var max = 16;
//var aryOrg = [...Array(max)].map((_, i) => i);
var aryOrg = [0,28,9,26,30,11,7,20,32,17,5,22,34,15,3,24,36,13,1,'00',27,10,25,29,12,8,19,31,18,6,21,33,16,4,23,35,14,2];
var max = aryOrg.length;
//アメリカンルーレット
$svg = $('<svg>',{id:'svg',width:w,height:w,viewBox:'0 0 '+w+' '+w});
$svg[0].id = 'svg';
var $h1 = $('<h1>').text(document.title);
/*
var $input = $('<input>',{type:'number',min:2,max:27}).css({
display:'block',
margin:'0 auto',
fontSize:'120px',
}).val(max);
$input.on('change', function(){
max = Number($(this).val());
colors = [];
aryOrg = [...Array(max)].map((_, i) => i);
aryOrg.forEach(function(v,i){
var h = i*(360/max);
colors.push('hsl('+h+',80%,50%)');
});
});
*/
$demo.after($h1);
$demo.after($('#other'));
var ns = 'http://www.w3.org/2000/svg';
var xlink = 'http://www.w3.org/1999/xlink';
svg = document.createElementNS(ns, 'svg');
$(svg).attr({width:w,height:w});
$(svg).attr({'xmlns:xlink':xlink});
$a = $('<a>');
$demo.append($a);
$stage = $('<div>',{id:'stage'});
$demo.append($stage);
$bar = $('<div>',{id:'bar'}).text('▼').addClass('down');
$stage.append($bar);
$stage.after($('#board'));
$body = $('html,body');
$bar.on('click', function(){
console.log(window.pageYOffset)
if(window.pageYOffset > window.innerHeight*2/3){
$body.animate({scrollTop:0},200);;
} else {
$body.animate({scrollTop:window.innerHeight},200);;
}
});
window.addEventListener('scroll', function() {
if(window.pageYOffset > window.innerHeight*2/3){
$bar.text('▲').removeClass('down');
} else {
$bar.text('▼').addClass('down');
}
});
$result = $('<div>',{id:'result'});
$result.addClass('ready');
$stage.append($result);
$stage.append($(svg));
g0 = document.createElementNS(ns, 'g');
g = document.createElementNS(ns, 'g');
g2 = document.createElementNS(ns, 'g');
$(svg).append($(g0));
$(svg).append($(g));
$(svg).append($(g2));
$(g).attr({id:'a'});
circle = document.createElementNS(ns, 'circle');
$(circle).attr({cx:w/2,cy:w/2,r:w/2-8,stroke:'#000',fill:'none'});
$(svg).append($(circle));
circle2 = document.createElementNS(ns, 'circle');
$(circle2).attr({cx:w/2,cy:w/2,r:w/2,stroke:'rgb(214, 177, 126)',fill:'rgb(61, 35, 20)'});
circle3 = document.createElementNS(ns, 'circle');
$(circle3).attr({cx:w/2,cy:w/2,r:w/3+16,stroke:'rgb(214, 177, 126)',fill:'none'});
circle4 = document.createElementNS(ns, 'circle');
$(circle4).attr({cx:w/2,cy:w/2,r:w/4,stroke:'rgb(181, 151, 94)',fill:'rgb(80, 50, 30)'});
$(g0).append($(circle2));
$(g2).append($(circle3));
$(g2).append($(circle4));
var colors = [];
aryOrg.forEach(function(v,i){
var h = i*(360/max);
if(v === 0 || v=== '00'){
color = 'rgb(48, 140, 67)';
} else if(i%2 === 0){
color = 'rgb(221, 31, 38)';
} else {
color = 'rgb(16, 16, 18)';
}
colors.push(color);
//colors.push('hsl('+h+',80%,50%)');
});
function drawArcPath(i, deg, v){
deg = deg || 0;
var path = document.createElementNS(ns, 'path');
var r = w/2-8;
var deg1 = deg+(i*(360/max));
var deg2 = deg1+(360/max);
var deg3 = (deg1+deg2)/2 - (deg2-deg1)/3;
var rad1 = deg1 * Math.PI /180;
var rad2 = deg2 * Math.PI /180;
var rad3 = deg3 * Math.PI /180;
var x1 = c + Math.cos(rad1) * r;
var y1 = c + Math.sin(rad1) * r;
var x2 = c + Math.cos(rad2) * r;
var y2 = c + Math.sin(rad2) * r;
var M = "M" + c + ',' + c +' ';
var L = "L" + x1 + ',' + y1 +' ';
var A = "A" + r + ',' + r +' ';
var a = '0 0,1 ';
var Z = '' + x2 + ',' + y2 + 'Z';
d = M + L + A + a + Z;
$(path).attr({d:d,stroke:'#000000'}).css({fill:colors[i]});
$(g).append($(path));
//テキスト挿入
var r3 = w/2 - w/12;
var x3 = c + Math.cos(rad3) * r3;
var y3 = c + Math.sin(rad3) * r3;
var x4 = c + Math.cos(rad2) * r3;
var y4 = c + Math.sin(rad2) * r3;
var path2 = document.createElementNS(ns, 'path');
var M = "M" + x3 + ',' + y3 +' ';
var A = "A" + r3 + ',' + r3 +' ';
var a = '1 0,1 ';
var L = 'L' + x4 + ',' + y4 + 'Z';
var d2 = M + L;
$(path2).attr({d:d2,stroke:'none',fill:'none',id:'textPath'+(i+1)});
$(g).append($(path2));
var text = document.createElementNS(ns, 'text');
var textPath = document.createElementNS(ns, 'textPath');
$(text).append($(textPath));
var fontSize = 32;
if(max >17){
fontSize = 24;
}
if(w < 640){
fontSize = 16;
}
textPath.setAttribute('text-anchor', 'middle');
textPath.setAttribute('font-size', fontSize);
textPath.setAttribute('font-weight', 'bol');
textPath.setAttribute('fill', '#ffffff');
textPath.setAttribute('href', '#textPath'+(i+1));
textPath.textContent = ' ' + (v);
$(g).append($(text));
//JavaScriptからSVGの文字列を操作/表示できない
//代替で●数を使う
/*
var cColor = '#000';
if(i%2===0){cColor = '#fff';}
var rrr = 7;
for(j=0;j<i+1;j++){
var rr = 2;
if(j%5===0){rr+=2;}
var x3 = c + Math.cos(rad3) * ( r * 9/10 - j*(rrr));
var y3 = c + Math.sin(rad3) * ( r * 9/10 - j*(rrr));
var circle = document.createElementNS(ns, 'circle');
$(circle).attr({cx:x3,cy:y3,r:rr}).css({fill:cColor});
$(g).append($(circle));
}
*/
/*
var path2 = document.createElementNS(ns, 'path');
$(path2).attr({d:d2,stroke:'none'});
$(path2).attr({'id':"t"+i,});
var text = document.createElementNS(ns, 'text');
var textpath = document.createElementNS(ns, 'textpath');
$(text).attr({'font-size':'32',stroke:'#000',dy:40});
$(textpath).attr({'xlink:href':"#t"+i,});
$(textpath).text(i);
$(text).append($(textpath));
$(path2).append($(text));
$(g).append($(path2));
*/
}
function drawBall(){
var deg = ballDeg;
var r = w/3;
var rr = w/90;
var rad = deg * Math.PI /180;
var x = c + Math.cos(rad) * r;
var y = c + Math.sin(rad) * r;
var path = document.createElementNS(ns, 'circle');
$(path).attr({cx:x,cy:y,r:rr,stroke:'#000000'}).css({fill:'#ffffff'});
$(g).append($(path));
}
function role(isSlow){
$result.text('')
t = 0;
pace = 7;
if(isSlow){
pace = 31;
}
timer = setInterval(function(){
t++;
if(isSlow){
speed -= t/(4*1000) - Math.random()*1/9;
} else {
speed = Math.random()*13+3;
}
if(speed<0){speed=0}
deg += speed;
if(isSlow){
ballSpeed = - Math.random()*2
} else {
ballSpeed = -3 - Math.random()*4
}
if(ballSpeed>0){ballSpeed=0;}
ballDeg += ballSpeed;
if(t%5===0){
se.currentTime = 0;
se.play();
}
draw();
}, pace);
}
function fixDeg(){
deg = Math.floor(deg%360);
degD = deg%(360/max);//キリよくする
deg -=degD;
deg = Math.floor(deg);
ballDeg = Math.floor(ballDeg % 360);
ballDegD = ballDeg%(360/max);//キリよくする
ballDeg -= ballDegD/2;
ballDeg = Math.floor(ballDeg);
}
function draw(){
$(g).empty();
aryOrg.forEach(function(v,i){
drawArcPath(i,deg, v);
});
drawBall(ballDeg);
}
function checkValDeg(){
deg2 = (deg-ballDeg);
if(deg2<0){
deg2+=360;
}
if(deg2>360){
deg2 = deg2 % 360;
}
var i = (aryOrg.length) * (360-deg2)/360;
var i = Math.floor(i);
var v = aryOrg[i];
//console.log(deg2);
console.log(v);
$result.text(v)
}
aryOrg.forEach(function(v,i){
drawArcPath(i,0, v);
});
var animateTransform = document.createElementNS(ns, 'animateTransform');
$(animateTransform).attr({
'xlink:href' : "#a",
attributeName : "transform",
type : "rotate",
from : "0 " + c +' '+ c,
to : "360 " + c +' '+ c,
dur : "0.47s",
repeatCount : "indefinite",
})
//$(g).append($(animateTransform).clone());
//role();
$result.addClass('stop');
$result.addClass('ready');
$result.on('click', function(){
var ele = $result;
if(ele.hasClass('stop')){
if(!ele.hasClass('ready')){
ready();
} else {
roleStart();
}
} else if(ele.hasClass('role')){
$result.removeClass('ready');
roleStop();
}
});
$result.find('small').on('click', function(){
$('html,body').scrollTop(window.innerHeight);
});
var roleStop = function(){
clearInterval(timer);
role(true);
var ele = $result;
if(ele.hasClass('stop') || ele.hasClass('slow')){
return;
}
var r = Math.random()*1000+400;
setTimeout(function(){
clearInterval(timer);
ele.addClass('stop');
ele.removeClass('slow');
ele.removeClass('role');
fixDeg();
draw();
checkValDeg();
setTimeout(function(){
checkResult($result.text());
}, 99);
}, r);
ele.addClass('slow');
}
var roleStart = function(){
var ele = $result;
if(ele.hasClass('stop') && !ele.hasClass('slow')){
ele.removeClass('stop');
role();
ele.addClass('role');
//$(g).append($(animateTransform).clone());
} else {
roleStop();
//$(svg).find('animateTransform').remove();
}
}
var score = 100;
var $score = $('#score');
$score.text(score);
var $table = $('#table');
var tableMax = 36;
var tableAry = [...Array(tableMax)].map((_, i) => i+1);
var tableTdW = 100/14;
var tableTdH = 90;
var top=0;
var left=0;
tableAry.forEach(function(v, i){
$div = $('<div>');
$table.append($div);
if(i%3===0){
top = tableTdH*2;
left+= tableTdW;
}
$i = $('<i>').text(v);
$div.append($i);
$div.attr({i:i,v:v});
$div.css({top:top+'px',left:left+'%'});
$div.addClass('data-num');
$div.addClass('data-num'+v);
//odd-even ではない
var index = aryOrg.indexOf(v);
if(index%2===0){
$div.addClass('red');
} else {
$div.addClass('black');
}
$o = $('<o>').text(35);
$div.append($o);
top -= tableTdH;
});
//縦線
top=0;
left= tableTdW - tableTdW/3/2;
index = 0;
for(let j=0;j<12-1;j++){
top = tableTdH*2 + tableTdH/3;
left+= tableTdW;
for(let i=0;i<3;i++){
index++;
$div = $('<b>');
$table.append($div);
$div.css({top:top+'px',left:left+'%'});
n1 = index;
n2 = index+3;
title = [n1,n2].join(',');
$div.attr({title:title});
$div.addClass('data-ary');
$o = $('<o>').text(17);
$div.append($o);
top -= tableTdH;
}
}
//横線
top=0;
left= tableTdW - tableTdW*2/3;
index = 0;
for(let j=0;j<12;j++){
top = tableTdH*2 - tableTdH*1/3/2;
left+= tableTdW;
for(let i=0;i<3-1;i++){
index=j*3+i+1;
$div = $('<b>');
$table.append($div);
$div.css({top:top+'px',left:left+'%'});
n1 = index;
n2 = index+1;
title = [n1,n2].join(',');
$div.attr({title:title});
$div.addClass('data-ary');
$o = $('<o>').text(17);
$div.append($o);
top -= tableTdH;
}
}
//横線:下
top=0;
left= tableTdW - tableTdW*2/3;
index = 0;
for(let j=0;j<12;j++){
top = tableTdH*3 - tableTdH*1/3/2;
left+= tableTdW;
index=j*3+1;
$div = $('<b>');
$table.append($div);
$div.css({top:top+'px',left:left+'%'});
n1 = index;
n2 = index+1;
n3 = index+2;
title = [n1,n2,n3].join(',');
$div.attr({title:title});
$div.addClass('data-ary');
$o = $('<o>').text(12);
$div.append($o);
}
//交差
top=0;
left= tableTdW - tableTdW/3/2;
index = 0;
for(let j=0;j<12-1;j++){
top = tableTdH*2 - tableTdH*1/3/2;
left+= tableTdW;
for(let i=0;i<3;i++){
index++;
if(i===3){continue;}
$div = $('<b>');
$table.append($div);
$div.css({top:top+'px',left:left+'%'});
n1 = index;
n2 = index+1;
n3 = index+3;
n4 = index+3+1;
title = [n1,n2,n3,n4].join(',');
$div.attr({title:title});
$div.addClass('data-ary');
$o = $('<o>').text(8);
$div.append($o);
top -= tableTdH;
}
}
//交差:下
top=0;
left= tableTdW - tableTdW/3/2;
index = 1;
for(let j=0;j<12-1;j++){
top = tableTdH*3 - tableTdH*1/3/2;
left+= tableTdW;
$div = $('<b>');
$table.append($div);
$div.css({top:top+'px',left:left+'%'});
n1 = index;
n2 = index+1;
n3 = index+2;
n4 = index+3;
n5 = index+4;
n6 = index+5;
title = [n1,n2,n3,n4,n5,n6].join(',');
$div.attr({title:title});
$div.addClass('data-ary');
index+=3;
$o = $('<o>').text(6);
$div.append($o);
}
left = 0;
top = 0;
[0,'00'].forEach(function(v, i){
$div = $('<div>');
$table.append($div);
$i = $('<i>').text(v);
$div.append($i);
$div.attr({i:i,v:v});
$div.css({top:top+'px',left:left+'%'});
$div.addClass('column0');
$div.addClass('data-'+v);
$o = $('<o>').text(35);
$div.append($o);
top += tableTdH*1.5;
});
left = tableTdW + tableTdW * (tableMax/3);
top = 0;
['2to1-3','2to1-2','2to1-1'].forEach(function(v, i){
$div = $('<div>');
$table.append($div);
$i = $('<i>').text(v);
$div.append($i);
$div.attr({i:i,v:v});
$div.css({top:top+'px',left:left+'%'});
$div.addClass('data-'+v);
$o = $('<o>').text(2);
$div.append($o);
top += tableTdH;
});
left = tableTdW;
top = tableTdH*3;
['1st-12','2nd-12','3rd-12'].forEach(function(v, i){
$div = $('<div>');
$table.append($div);
$i = $('<i>').text(v);
$div.append($i);
$div.attr({i:i,v:v});
$div.css({top:top+'px',left:left+'%'});
$div.addClass('column4');
$div.addClass('data-'+v);
$o = $('<o>').text(2);
$div.append($o);
left += tableTdW*4;
});
left = tableTdW;
top = tableTdH*4;
['1-18','EVEN','RED','BLACK','ODD','19-36'].forEach(function(v, i){
$div = $('<div>');
$table.append($div);
$i = $('<i>').text(v);
$div.append($i);
$div.attr({i:i,v:v});
$div.css({top:top+'px',left:left+'%'});
$div.addClass('column2');
$div.addClass('data-'+v);
left += tableTdW*2;
if(v==='RED'){
$div.addClass('red');
}
if(v==='BLACK'){
$div.addClass('black');
}
$o = $('<o>').text(1);
$div.append($o);
});
$li = $('#table').find('div,b');
var start = function(){
roleStart();
}
var ready = function(){
$result.addClass('ready');
$li.removeClass('hit');
$li.removeAttr('hitCount');
$li.find('c').remove();
$result.empty();
$p = $('<small>').text('= BET TIME =');
$result
.append($p);
}
var checkResult = function(nn){
var n = Number(nn);
console.log(n);
if(n===0){
return;
}
if(n>0){
$('.data-num'+n).addClass('hit');
}
if(n>=1 && n<=18){
$('.data-'+'1-18').addClass('hit');
}
if(n>=19 && n<=36){
$('.data-'+'19-36').addClass('hit');
}
if(n>=1 && n<=12){
$('.data-'+'1st-12').addClass('hit');
} else if (n>=13 && n<=24){
$('.data-'+'2nd-12').addClass('hit');
} else {
$('.data-'+'3rd-12').addClass('hit');
}
if(n%3 === 1){
$('.data-'+'2to1-1').addClass('hit');
} else if (n%3 === 2){
$('.data-'+'2to1-2').addClass('hit');
} else {
$('.data-'+'2to1-3').addClass('hit');
}
if(n>=19 && n<=36){
$('.data-'+'19-36').addClass('hit');
}
if(n%2===0){
$('.data-'+'EVEN').addClass('hit');
} else {
$('.data-'+'ODD').addClass('hit');
}
var index = aryOrg.indexOf(n);
if(index%2===0){
$('.data-'+'RED').addClass('hit');
} else {
$('.data-'+'BLACK').addClass('hit');
}
$('.data-ary').each(function(){
var aryEle = $(this);
var text = $(this).attr('title');
var ary = text.split(',');
ary.forEach(function(a){
var a = Number(a);
if(a === n){
aryEle.addClass('hit');
}
})
});
var scoreBefore = score;
$hits = $('.hit');
$hits.each(function(){
var ele = $(this);
var $bet = ele.find('c');//chip
betCount = $bet.length || 0;
var odds = ele.find('o').text();
odds = Number(odds);
score += betCount;
score += betCount * odds;
});
if(score > scoreBefore+1){
sePach.play();
}
$score.text(score);
}
var bet = function(ele){
if(!$result.hasClass('ready')){
return;
}
var $bet = ele.find('c');//chip
var betCount = $bet.length || 0;
if(betCount > 4){
$bet.remove();
score+=5;
} else {
$b = $('<c>');
ele.append($b);
score--;
}
$score.text(score);
}
$score.on('click', function(){
$('html,body').scrollTop(0);
});
$table.on('click', function(){
if(!$result.hasClass('ready')){
ready();
}
});
$li.on('click', function(){
var ele = $(this);
bet(ele)
});
});
CSS
@font-face {
font-family: LeagueGothic;
src: url(/fonts/LeagueGothic-Regular.ttf);
}
html,body{
background-color:rgb(0, 129, 61);
}
*{
box-sizing:border-box;
}
#demo{
position:relative;
left:0;
top:0;
font-family: LeagueGothic, Meiryo;
text-align:center;
user-select:none;
color:#fff;
}
#stage,
#board{
position:relative;
left:0;
top:0;
min-height:100vh;
}
#stage{
display: grid;
place-items: center;
}
#rule{
font-family: LeagueGothic, Meiryo;
}
#bar{
position:absolute;
left:0;
bottom:-5vh;
width:100%;
font-size:40px;
font-weight:bold;
text-align:center;
cursor:pointer;
z-index:5;
}
#bar.down{
left:0;
bottom:0;
}
#bar:hover{
background-color:rgba(255,255,255,0.2);
}
#board{
padding-top:5vh;
}
#demo p{
display:block;
position:absolute;
left:0;
top:0;
}
#demo svg{
display:inline-block;
margin-top:20px;
}
#demo p{
left:calc(50% - 20px);
width: 0;
height: 0;
border-style: solid;
border-width: 48px 20px 0 20px;
border-color: #000000 transparent transparent transparent;
z-index:3;
}
svg textPath{
text-indent:-2em;
text-anchor:middle;
dominant-baseline: middle;
}
#result{
position:absolute;
z-index:3;
top:0px;
left:0;
width:100%;
height:100vh;
line-height:100vh;
color:#fff;
font-size:20vmin;
font-weight:bold;
text-align:center;
cursor:pointer;
}
#result small{
font-size:32px;
}
#score{
color:#fff;
font-size:160px;
font-weight:bold;
text-align:center;
}
#tableImg{
width:100%;
}
#table{
position:relative;
left:0;
top:0;
height:480px;
user-select:none;
}
#table div{
position:absolute;
width:calc(100% / 14);
height:90px;
border:2px solid rgba(255,255,255,0.6);
text-align:center;
line-height:90px;
overflow:hidden;
}
#table b{
display:block;
position:absolute;
width:calc(100% / 14 / 3);
height:calc(90px / 3);
text-align:center;
line-height:30px;
border-radius:50%;
}
#table div:hover{
border:4px solid rgba(255,255,255,1);
}
#table b:hover{
background-color:rgba(255,255,255,0.4);
}
#table div.hit{
border:4px solid rgb(255, 255, 0);
}
#table div.column0{
height:135px;
line-height:135px;
}
#table div.column2{
width:calc(100% / 14 * 2);
}
#table div.column4{
width:calc(100% / 14 * 4);
}
#table div i{
color:#fff;
font-size: 32px;
font-family: LeagueGothic, Meiryo;
}
#table div.black{
background-color: rgb(16, 16, 18);
}
#table div.red{
background-color: rgb(221, 31, 38);
}
o{
display:none;
}
c{
display:inline-block;
width:16px;
height:12px;
background-image:url(../js-game-dice-sicbo/chip.png);
background-size:cover;
position:absolute;
left:calc(50% - 16px / 2);
bottom:8px;
border-radius:50%;
}
c:nth-of-type(1){
bottom:8px;
}
c:nth-of-type(2){
bottom:12px;
}
c:nth-of-type(3){
bottom:16px;
}
c:nth-of-type(4){
bottom:20px;
}
c:nth-of-type(5){
bottom:24px;
}
#rule{
padding:5vh;
}
/*
@media (max-width: 600px) {
#demo{
transform:scale(0.5);
}
}
*/
#other{
padding:8px;
background-color:rgb(0, 129, 61);
}
#rule{
margin:2px;
padding:8px;
background-color:#fff;
border-radius:8px;
}
#rule *{
padding:8px;
}
HTML
ページのソースを表示 : Ctrl+U , DevTools : F12
view-source:https://hi0a.com/demo/-js/js-game-roulette-casino/
ABOUT
hi0a.com 「ひまアプリ」は無料で遊べるミニゲームや便利ツールを公開しています。
プログラミング言語の動作デモやWEBデザイン、ソースコード、フロントエンド等の開発者のための技術を公開しています。
必要な機能の関数をコピペ利用したり勉強に活用できます。
プログラムの動作サンプル結果は画面上部に出力表示されています。
環境:最新のブラウザ GoogleChrome / Windows / Android / iPhone 等の端末で動作確認しています。
画像素材や音素材は半分自作でフリー素材配布サイトも利用しています。LINK参照。
動く便利なものが好きなだけで技術自体に興味はないのでコードは汚いです。
途中放置や実験状態、仕様変更、API廃止等で動かないページもあります。