Skip to content

Instantly share code, notes, and snippets.

@motsu0
Last active February 16, 2020 18:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save motsu0/80327063285e488b8e1fcfd36cc0dc93 to your computer and use it in GitHub Desktop.
Save motsu0/80327063285e488b8e1fcfd36cc0dc93 to your computer and use it in GitHub Desktop.
#game-area{
position: relative;
}
#play-area{
padding: 15px 0;
position: relative;
user-select: none;
}
#play-area,#controller{
background-color: #43A047;
}
#controller{
padding: 10px;
text-align: right;
}
#joker-area{
width: 100%;
position: absolute;
top: 10px;
right: 10px;
text-align: right;
pointer-events: none;
}
.joker{
pointer-events: auto;
}
.pyramid-row{
line-height: 0;
text-align: center;
font-size: 0;
letter-spacing: 0;
}
.pyramid-row+.pyramid-row{
margin-top: -9%;
}
#hand-area{
display: flex;
justify-content: space-evenly;
margin: 10px 0;
}
#reload-meter{
padding-right: 10px;
text-align: right;
color: white;
}
.card{
width: 12%;
max-height: calc((95vh - 130px) / 4.4);
margin: 0 2px;
cursor: pointer;
}
.selected{
box-shadow: 0 0 0 4px #A1436A;
}
.hidden{
visibility: hidden;
}
#before-init,#cleared{
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
background-color: rgba(0,0,0,.7);
color: white;
font-size: 2.5rem;
line-height: 1.5em;
text-align: center;
}
#cleared.hide{
display: none;
}
@media screen and (min-width:481px) {
.pyramid-row+.pyramid-row{
margin-top: calc((130px - 95vh) * 0.6 / 4.4);
}
.card{
width: auto;
height: calc((95vh - 130px) / 4.4);
margin: 0 4px;
}
#before-init,#cleared{
font-size: 5rem;
}
.selected{
box-shadow: 0 0 0 7px #A1436A;
}
}
<div id="game-area">
<div id="controller">
<button id="new-game">New Game</button>
<button id="re-start">Re Start</button>
</div>
<div id="play-area">
<div id="joker-area">
<canvas class="card joker" width="100px" height="162px"></canvas>
<canvas class="card joker" width="100px" height="162px"></canvas>
</div>
<div id="pyramid">
<div class="pyramid-row">
<canvas class="card mt-card" width="100px" height="162px"></canvas>
</div>
<div class="pyramid-row">
<canvas class="card mt-card" width="100px" height="162px"></canvas>
<canvas class="card mt-card" width="100px" height="162px"></canvas>
</div>
<div class="pyramid-row">
<canvas class="card mt-card" width="100px" height="162px"></canvas>
<canvas class="card mt-card" width="100px" height="162px"></canvas>
<canvas class="card mt-card" width="100px" height="162px"></canvas>
</div>
<div class="pyramid-row">
<canvas class="card mt-card" width="100px" height="162px"></canvas>
<canvas class="card mt-card" width="100px" height="162px"></canvas>
<canvas class="card mt-card" width="100px" height="162px"></canvas>
<canvas class="card mt-card" width="100px" height="162px"></canvas>
</div>
<div class="pyramid-row">
<canvas class="card mt-card" width="100px" height="162px"></canvas>
<canvas class="card mt-card" width="100px" height="162px"></canvas>
<canvas class="card mt-card" width="100px" height="162px"></canvas>
<canvas class="card mt-card" width="100px" height="162px"></canvas>
<canvas class="card mt-card" width="100px" height="162px"></canvas>
</div>
<div class="pyramid-row">
<canvas class="card mt-card" width="100px" height="162px"></canvas>
<canvas class="card mt-card" width="100px" height="162px"></canvas>
<canvas class="card mt-card" width="100px" height="162px"></canvas>
<canvas class="card mt-card" width="100px" height="162px"></canvas>
<canvas class="card mt-card" width="100px" height="162px"></canvas>
<canvas class="card mt-card" width="100px" height="162px"></canvas>
</div>
<div class="pyramid-row">
<canvas class="card mt-card" width="100px" height="162px"></canvas>
<canvas class="card mt-card" width="100px" height="162px"></canvas>
<canvas class="card mt-card" width="100px" height="162px"></canvas>
<canvas class="card mt-card" width="100px" height="162px"></canvas>
<canvas class="card mt-card" width="100px" height="162px"></canvas>
<canvas class="card mt-card" width="100px" height="162px"></canvas>
<canvas class="card mt-card" width="100px" height="162px"></canvas>
</div>
</div>
<div id="hand-area">
<canvas id="discard" class="card" width="100px" height="162px"></canvas>
<canvas id="using" class="card" width="100px" height="162px"></canvas>
<canvas id="deck" class="card" width="100px" height="162px"></canvas>
</div>
<div id="reload-meter"></div>
<div id="cleared">Game Clear!!</div>
</div>
<div id="before-init">準備中...</div>
</div>
const unit_w = 100;
const unit_h = 162;
const limit = 2;
let mt_ctx = [];
let mt_map=[];
let mtc = 0;
[...document.getElementsByClassName('pyramid-row')].forEach(row=>{
let ar = [];
[...row.getElementsByClassName('mt-card')].forEach(el=>{
ar.push([el,mtc])
mtc++;
});
mt_map.push(ar);
});
const mt_cards = document.getElementsByClassName('mt-card');
[...mt_cards].forEach((mt_card,i)=>{
mt_ctx.push(mt_card.getContext('2d'));
mt_card.addEventListener('click',(e)=>{
e.stopPropagation();
click_mt(e,i,row_num(i));
});
});
const selecteds = document.getElementsByClassName('selected');
const discard = document.getElementById('discard');
const using = document.getElementById('using');
const deck = document.getElementById('deck');
const hand_ctx ={
'discard': discard.getContext('2d'),
'using': using.getContext('2d'),
'deck': deck.getContext('2d')
}
deck.addEventListener('click',(e)=>{e.stopPropagation();click_deck();});
using.addEventListener('click',(e)=>{e.stopPropagation();click_using();});
discard.addEventListener('click',(e)=>{e.stopPropagation();click_discard();});
const jokers = document.getElementsByClassName('joker');
[...jokers].forEach(joker=>{
joker.addEventListener('click',(e)=>{
e.stopPropagation();
click_joker(e.target);
});
});
const joker_ctx = [jokers[0].getContext('2d'),jokers[1].getContext('2d')];
document.getElementById('new-game').addEventListener('click',reset);
document.getElementById('re-start').addEventListener('click',init);
const reload_meter = document.getElementById('reload-meter');
const cleared = document.getElementById('cleared');
document.getElementById('play-area').addEventListener('click',cansel);
let card_set;
let mt_set;
let deck_set;
let using_set;
let discard_set;
let imgset;
let imgback;
let imgreload;
let imgnocard;
let imglimit;
let selected_num = false;
let mt_selected = false;
let chance;
Promise.all([
load_img('../img/pcard/p-card.png'),
load_img('../img/pcard/p-card-back.png'),
load_img('../img/pcard/p-card-reload.png'),
load_img('../img/pcard/p-card-nocard.png'),
load_img('../img/pcard/p-card-limit.png')
]).then(val=>{
imgset = val[0];
imgback = val[1];
imgreload = val[2];
imgnocard = val[3];
imglimit= val[4];
reset();
document.getElementById('before-init').style.display = 'none';
});
function reset(){
card_set = [];
for(let i=1;i<=4;i++){
for(let j=1;j<=13;j++){
card_set.push([i,j]);
}
}
for(let i=card_set.length-1;i>=1;i--){
const j = randomMN(0,i);
[card_set[j],card_set[i]] = [card_set[i],card_set[j]];
}
mt_set = card_set.slice(0,28);
init();
}
function init(){
cleared.classList.add('hide');
//init draw
[...mt_cards].forEach((mt_card,i)=>{
if(i<=20){
mt_card.classList.remove('active');
draw(mt_ctx[i],imgback,false);
}else{
mt_card.classList.add('active');
draw(mt_ctx[i],imgset,true,mt_set[i][1],mt_set[i][0]);
}
mt_card.classList.remove('hidden');
});
discard.classList.remove('active');
using.classList.remove('active');
deck.classList.add('active');
hand_ctx.discard.clearRect(0,0,unit_w,unit_h);
hand_ctx.using.clearRect(0,0,unit_w,unit_h);
draw(hand_ctx.deck,imgback,false);
[...jokers].forEach((joker,i)=>{
joker.classList.add('active');
joker.classList.remove('hidden');
draw(joker_ctx[i],imgset,true,1,5);
});
cansel();
//set hand-area
deck_set = card_set.slice(28);
using_set = [];
discard_set = [];
chance = limit;
reload_meter.textContent = `山札再使用:残り${chance}回`;
}
function load_img(src){
return new Promise(resolve=>{
const img = new Image();
img.onload = () => resolve(img);
img.src = src;
});
}
function draw(ctx,img,isOpen,suit,num){
ctx.clearRect(0,0,unit_w,unit_h);
if(isOpen){
ctx.drawImage(img,(suit-1)*unit_w,(num-1)*unit_h,unit_w,unit_h,0,0,unit_w,unit_h);
}else{
ctx.drawImage(img,0,0);
}
}
function row_num(x){
for(let i=0;i<=6;i++){
const n = ((i+1)*(i+2)/2)-1;
if(x<=n) return i;
}
}
function click_mt(e,id,row){
const card = e.target;
if(!card.classList.contains('active')) return;
if(selected_num){
//second select
if(!card.classList.contains('selected')){
//another select
if(selected_num+mt_set[id][1]==13||selected_num=='joker'){
if(mt_set[id][1]==13){
//joker → K
del_cards([mt_cards[id]]);
}else{
//else
del_cards([selecteds[0],mt_cards[id]]);
}
}
}
selecteds[0].classList.remove('selected');
selected_num = false;
}else{
//first select
if(mt_set[id][1]==13){
//first K
del_cards([mt_cards[id]]);
}else{
selected_num = mt_set[id][1];
card.classList.add('selected');
}
}
}
function click_using(){
if(!using.classList.contains('active')) return;
if(selected_num){
//second select
if(selected_num+using_set[0][1]==13&&selecteds[0].classList.contains('mt-card')){
del_cards([selecteds[0],using]);
}
selecteds[0].classList.remove('selected');
selected_num = false;
}else{
//first select
if(using_set[0][1]==13){
del_cards([using]);
}else{
using.classList.add('selected');
selected_num = using_set[0][1];
}
}
}
function click_discard(){
if(!discard.classList.contains('active')) return;
if(selected_num){
//second select
if(selected_num+discard_set[discard_set.length-1][1]==13&&selecteds[0].classList.contains('mt-card')){
del_cards([selecteds[0],discard]);
}
selecteds[0].classList.remove('selected');
selected_num = false;
}else{
//first select
if(discard_set[discard_set.length-1][1]==13){
del_cards([discard]);
}else{
discard.classList.add('selected');
selected_num = discard_set[discard_set.length-1][1];
}
}
}
function click_joker(joker){
if(!joker.classList.contains('active')) return;
if(selected_num){
//second_select
if(selecteds[0].classList.contains('mt-card')){
del_cards([selecteds[0],joker]);
}
selecteds[0].classList.remove('selected');
selected_num = false;
}else{
//first select
joker.classList.add('selected');
selected_num = 'joker';
}
}
function click_deck(){
if(!deck.classList.contains('active')) return;
if(selecteds.length>0) selecteds[0].classList.remove('selected');
selected_num = false;
if(deck_set.length==0){
//reload
if(using_set.length>0){
discard_set.push(using_set[0]);
using_set.shift();
}
if(discard_set.length>0){
deck_set = discard_set.slice(0);
discard_set = [];
}
hand_ctx.discard.clearRect(0,0,unit_w,unit_h);
discard.classList.remove('active');
hand_ctx.using.clearRect(0,0,unit_w,unit_h);
using.classList.remove('active');
if(deck_set.length==0){
//no card
deck.classList.remove('active');
draw(hand_ctx.deck,imgnocard,false);
}else{
draw(hand_ctx.deck,imgback,false);
chance--;
reload_meter.textContent = `山札再使用:残り${chance}回`;
}
}else{
//use
if(using_set.length>0){
discard_set.push(using_set[0]);
draw(hand_ctx.discard,imgset,true,discard_set[discard_set.length-1][1],discard_set[discard_set.length-1][0]);
discard.classList.add('active');
using_set.shift();
}
using_set.unshift(deck_set[0]);
draw(hand_ctx.using,imgset,true,deck_set[0][1],deck_set[0][0]);
using.classList.add('active');
deck_set.shift();
if(deck_set.length==0){
if(chance==0){
deck.classList.remove('active');
draw(hand_ctx.deck,imglimit,false);
}else{
draw(hand_ctx.deck,imgreload,false);
}
}
}
}
function cansel(){
[...selecteds].forEach(v=>v.classList.remove('selected'));
selected_num = false;
}
function del_cards(arr){
arr.forEach(card=>{
if(card.classList.contains('mt-card')){
card.classList.add('hidden');
card.classList.remove('active');
}else if(card.classList.contains('joker')){
card.classList.add('hidden');
card.classList.remove('active');
}else if(card.id=='using'){
using_set.shift();
hand_ctx.using.clearRect(0,0,unit_w,unit_h);
using.classList.remove('active');
}else if(card.id=='discard'){
discard_set.pop();
if(discard_set.length>0){
draw(hand_ctx.discard,imgset,true,discard_set[discard_set.length-1][1],discard_set[discard_set.length-1][0]);
}else{
hand_ctx.discard.clearRect(0,0,unit_w,unit_h);
discard.classList.remove('active');
}
}
});
if(arr.indexOf(mt_cards[0])!=-1){
game_clear();
return;
}
mt_open();
}
function mt_open(){
mt_map.forEach((row,r)=>{
row.forEach((card,c)=>{
if(card[0].classList.contains('hidden')||card[0].classList.contains('active')) return;
if(mt_map[r+1][c][0].classList.contains('hidden')&&mt_map[r+1][c+1][0].classList.contains('hidden')){
card[0].classList.add('active');
const id = mt_map[r][c][1];
draw(mt_ctx[id],imgset,true,mt_set[id][1],mt_set[id][0]);
}
});
});
}
function game_clear(){
cleared.classList.remove('hide');
}
function randomMN(m,n){
const d = Math.max(m,n)-Math.min(m,n);
return Math.floor(Math.random()*(d+1)+Math.min(m,n));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment