working waste pile

This commit is contained in:
2024-09-23 16:20:33 +10:00
parent 4b174b3c36
commit cdf436c5a6
2 changed files with 328 additions and 137 deletions

View File

@@ -3,7 +3,7 @@
<head> <head>
<style> <style>
html { html {
background-color: Azure; background-color:#00CEC8`;
} }
/*canvas styling*/ /*canvas styling*/
#canvas { #canvas {
@@ -28,6 +28,7 @@
</head> </head>
<body> <body>
<canvas id="canvas" width="400" height="300"> </canvas> <canvas id="canvas" width="400" height="300"> </canvas>
<input id="clickMe" type="button" value="DrawStock" onclick="game_instance.draw_stock();" />
<input id="clickMe" type="button" value="DrawStock" onclick="game_instance.reset();" />
</body> </body>
</html> </html>

460
game.js
View File

@@ -14,11 +14,9 @@ class Stack {
pop() { pop() {
//Check that the stack is not empty //Check that the stack is not empty
//Remove the last element from the stack and return it //Remove the last element from the stack and return it
if (this.isEmpty() == false){ var card = this.#items.pop();
return this.#items.pop() console.log(this.#items)
} else { return card
return false;
}
} }
peek() { peek() {
@@ -52,90 +50,14 @@ class Stack {
to_array(){ to_array(){
return this.#items; return this.#items;
} }
}
//column class unshift(card){
class Column extends Stack{ console.log(card);
constructor(){ this.#items.unshift(card);
super();
}
}
//stock stack
class Stock extends Stack {
constructor(){
super();
}
//append card back to stock after wastepile exceeds threshold CRUDE
append(card){
var items = super.get_items();
items.unshift(card);
super.set_items(items);
}
}
class WastePile extends Stack {
constructor(){
super();
}
//clearing waste pile by popping the cards one by one
clear () {
for (i=super.size();i--;i>-1){
super.pop();
}
}
//determines if the waste pile has met the threshold of 3
threshold (){
if (super.size() == 3){
return true;
} else {
return false;
}
}
}
//Object for board layout
class Board {
#waste_pile
#stock_pile
#foundations
#tableau
#deck
constructor (){
//init a deck
this.#deck = new Deck();
this.#tableau = new Array();
this.#stock_pile = new Stock();
this.#waste_pile = new WastePile();
//initialise the 7 columns
for (var i=1; i<8; i++){
this.#tableau.push(new Column());
}
//initialise the value in the 7 columns
for (var j = 1; j<8; j++){
for (var k = j; k>0; k--){
this.#tableau[j-1].push(this.#deck.drawCard());
} }
} }
var length = this.#deck.getSize();
//initialise the stock pile
for (var k=0; k <= length; k++){
this.#stock_pile.push(this.#deck.drawCard());
}
//reveal top card except stock pile, otherwise it'd be cheating
}
}
//base class for element //base class for element
class Element{ class Element{
@@ -171,6 +93,33 @@ class Background extends Element {
} }
//the round rectangle shape thingy for foundation
class Placeholder extends Element {
constructor(x,y,dx,dy){
super(x,y)
this.x = x;
this.ox = x;
this.y = y;
this.oy = y;
this.odx = dx;
this.dx = dx;
this.ody = dy;
this.dy = dy;
}
resize(scale){
this.dx = this.odx * scale[0];
this.dy = this.ody * scale[1];
this.x = this.ox*scale[0];
this.y = this.oy*scale[1]
}
render(ctx){
ctx.roundRect(this.x, this.y, this.dx, this.dy, 10)
ctx.stroke();
}
}
//view class for different views to extend on //view class for different views to extend on
class View { class View {
#element_list #element_list
@@ -191,17 +140,63 @@ class View {
} }
} }
add_element(e){ update_element(element_list){
this.#element_list.append(e); this.#element_list=element_list;
}
add_elemnt(e){
this.#element_list.push(e);
}
get_element_list(){
return this.#element_list;
} }
} }
class MenuView extends View {
constructor(){
super([new MenuBgView])
}
}
class MenuBgView extends Element {
constructor(x,y,dy,dx){
super(x,y);
this.ox = x;
this.oy = y;
this.dx = dx;
this.dy = dy;
this.odx = dx;
this.ody = dy;
}
resize(scale){
this.dx = this.odx * scale[0];
this.dy = this.ody * scale[1];
this.x = this.ox*scale[0];
this.y = this.oy*scale[1];
}
render(ctx){
ctx.rect(this.x, this.y, this.dx, this.dy);
ctx.fill();
}
}
//view for single card, bad naming I suppose, as it is not a view (really) more of a element //view for single card, bad naming I suppose, as it is not a view (really) more of a element
class CardView extends Element { class CardView extends Element {
#revealed #revealed
#img #img
constructor(revealed, x, y, card){ constructor(revealed, x, y, card, dx, dy){
super(x,y); super(x,y)
this.dx = dx;
this.dy = dy;
this.odx = dx;
this.ody = dy;
this.ox = x;
this.oy = y;
this.#revealed = revealed; this.#revealed = revealed;
this.#img = new Image(); this.#img = new Image();
this.card = card; this.card = card;
@@ -213,65 +208,183 @@ class CardView extends Element {
} }
render(ctx){ render(ctx){
ctx.drawImage(this.#img, x, y); ctx.drawImage(this.#img, this.x, this.y, this.dx, this.dy);
}
resize(scale){
this.dx = this.odx * scale[0];
this.dy = this.ody * scale[1];
this.x = this.ox*scale[0];
this.y = this.oy*scale[1];
} }
} }
//0 orientation for landscape 1 orientation for portrait //0 orientation for landscape 1 orientation for portrait
class StackView extends View{ class StackView extends View{
#orientation orientation
constructor (orientation,element_list){ oxy
ody
xy
dy
offset
constructor (orientation, reveal_all, element_list, odx, ody, ox, oy){
super(element_list) super(element_list)
this.#orientation = orientation; this.orientation = orientation;
this.odx = ody;
this.ody = ody;
this.ox = ox;
this.oy = oy;
this.dx = odx;
this.dy = ody;
this.x = ox;
this.y = oy;
this.reveal_all = reveal_all;
}
//parses the passed card array serialised by the stack class, into element list with card views
array_parser(arr){
var tmp_element_list = new Array();
for (var i=0;i<arr.length;i++){
//if last card, change the image to reveal
if (i+1 == arr.length && this.reveal_all == false) {
tmp_element_list.push(new CardView(true, this.x,this.y+(20*i),arr[i], this.dx, this.dy))
}
else if (i+1 != arr.length && this.reveal_all == false){
tmp_element_list.push(new CardView(false, this.x,this.y+(20*i),arr[i], this.dx, this.dy))
}
else if (this.reveal_all==true){
tmp_element_list.push(new CardView(true, this.x,this.y+(20*i),arr[i], this.dx, this.dy))
}
}
return tmp_element_list
}
update_element(element_list){
super.update_element(element_list);
} }
} }
//view for the stock stack //view for the stock stack
class StockView extends StackView{ class StockView extends StackView{
#card_list
#stack //the reveal determines if all cards of the stack is revealed or only last of the card is revealed
constructor (stack){ //while the CardView determines if the particular view is visible or not
super(0, [new CardView(false,50,20)], stack.peek()); constructor (stack, reveal){
this.#stack = stack; super(0, reveal,[new CardView(false,50,20, stack.peek(),210 , 300)], 210, 300, 50, 20);
this.stack = stack;
} }
on_empty() { on_empty() {
} }
draw(){
console.log(this.stack);
var card = this.stack.pop();
return card;
}
on_receive(array){
for (var i=0;i<array.length;i++){
this.stack.unshift(array[i]);
}
}
}
//view for the foundation, it is not displayed as a stack so it is a single element
class FoundationView extends View {
constructor (){
//well we haven't initialised the cards yet, shove it in later
super([]);
//this is where the cards sit
this.stack = new Stack();
//temp coords
var x = 700
var y = 20
for (var i=0; i<4; i++){
//append the placeholders into the array
super.add_elemnt(new Placeholder(x,y,210,300))
//previous placeholder and gap
x+=246.66;
}
}
on_empty(){
//obviously replace it with the rectangle
}
//when the card is placed on a particular foundation, show it!
on_put(){
}
} }
//view for the waste stack //view for the waste stack
class WasteView extends StackView{ class WasteView extends StackView{
constructor(){ constructor(){
super(0); super(0, true, [], );
this.list = []
this.elist = []
this.x = 340
this.dx = 210
this.dy = 300
this.y= 20
}
add(card, scale){
console.log(card, this.list.length);
if (this.list.length < 3){
this.list.push(card);
this.elist.push(new CardView(true, this.x, this.y, card, this.dx, this.dy))
super.update_element(this.elist);
super.resize(scale);
this.x+=30;
} else if (this.list.length == 3) {
var tmplst = this.list;
this.list = [];
this.elist = [];
this.x=340;
this.dx=210;
this.dy=300;
this.y=20;
this.list.push(card);
this.elist.push(new CardView(true, this.x, this.y, card, this.dx, this.dy))
super.update_element(this.elist);
super.resize(scale);
this.x+=30;
return tmplst;
}
}
empty_to_stock(){
return (this.list);
} }
} }
//view for the vertical columns //view for the vertical columns
class ColumnView extends StackView { class ColumnView extends StackView {
constructor(){ constructor(stack, element_list, ox, oy, odx, ody){
super(1); super(1, false, element_list, ox, oy, odx, ody);
} this.stack=stack;
} console.log(super.array_parser(this.stack.to_array()));
//view for the foundations
class FoundationView extends StackView {
constructor(){
super(1);
} }
} }
class TableauView{
//passed board object to gen view class InputMgr {
constructor (board){
constructor(cur_view_arr){
this.cur_view_arr = cur_view_arr;
} }
} }
//canva rendering manager //canva rendering manager
class RenderMgr{ class RenderMgr{
@@ -283,28 +396,24 @@ class RenderMgr{
constructor(ctx){ constructor(ctx){
this.#ctx = ctx; this.#ctx = ctx;
//init bg //init bg
this.#cur_view = new View([new Background()]); this.#cur_view = [new View([new Background()])];
} }
resize(scale){ resize(scale){
//resize every single element present on view for (var i=0;i<this.#cur_view.length;i++){
this.#cur_view.resize(scale); this.#cur_view[i].resize(scale);
}
} }
render(){ render(){
this.#cur_view.render(this.#ctx); for (var i=0;i<this.#cur_view.length;i++){
this.#cur_view[i].render(this.#ctx);
}
requestAnimationFrame(this.render.bind(this)) requestAnimationFrame(this.render.bind(this))
} }
set_view(array_of_views){
parse_view_json(json_str) { this.#cur_view = array_of_views;
var view_list = []
console.log(json_str);
for (var e in json_str){
view_list.push(JSON.parse(e));
}
console.log(view_list);
} }
} }
@@ -312,22 +421,27 @@ class RenderMgr{
class KlondikeGame { class KlondikeGame {
#size_modifier #size_modifier
#board #deck
#ctx #ctx
#scale_modifier #scale_modifier
#mgr #mgr
#tableau
#stock_pile
#waste_pile
#foundations
constructor (){ constructor (){
//intialise a new board //intialise views
this.#board = new Board(); this.init_views();
console.log("initialised board"); console.log("initialised views");
//grab context for render manager //grab context for render manager
this.#ctx = document.getElementById("canvas").getContext("2d"); this.#ctx = document.getElementById("canvas").getContext("2d");
console.log(this.#board);
//initialise render manager //initialise render manager
this.#mgr = new RenderMgr(this.#ctx); this.#mgr = new RenderMgr(this.#ctx);
requestAnimationFrame(this.#mgr.render.bind(this.#mgr)); requestAnimationFrame(this.#mgr.render.bind(this.#mgr));
var tmp_view = [new View([new Background()])];
this.#mgr.set_view(tmp_view.concat(this.#tableau, this.#stock_pile, this.#foundations, this.#waste_pile));
console.log(tmp_view);
} }
//update scale modifier, however only currently fixed to 16:9 aspect ratio. //update scale modifier, however only currently fixed to 16:9 aspect ratio.
@@ -337,10 +451,86 @@ class KlondikeGame {
this.#mgr.resize(this.#scale_modifier); this.#mgr.resize(this.#scale_modifier);
} }
//intitialise views, replacing the board class
init_views (){
this.#deck = new Deck();
this.#tableau = new Array();
var tmp_tableau = new Array()
var tmp_tableau_list = new Array()
//deal and populate the columns, in the temporary array
for (var j = 1; j<8; j++){
tmp_tableau.push(new Stack())
for (var k = j; k>0; k--){
tmp_tableau[j-1].push(this.#deck.drawCard());
}
}
//serialise it to array
for (var j = 1; j<8; j++){
tmp_tableau_list.push(tmp_tableau[j-1].to_array())
}
var tmp_tableau_element_list = new Array();
//dump into view
//tmp pos
var x = 50
var y = 540
var dx = 180
var dy = 270
//this current list is a 2d array
for (var h=0; h<7;h++){
var tmp_list = new Array()
for (var i=0;i<tmp_tableau_list[h].length;i++){
//if last card, change the image to reveal
if (i+1 == tmp_tableau_list[h].length) {
tmp_list.push(new CardView(true, x,y,tmp_tableau_list[h][i], dx, dy));
}
else if (i+1 != tmp_tableau_list[h].length) {
tmp_list.push(new CardView(false, x,y,tmp_tableau_list[h][i], dx, dy));
}
y+=20
}
tmp_tableau_element_list.push(tmp_list);
x+=273.3
y=540
}
for (var i=0;i<7;i++){
this.#tableau.push(new ColumnView(tmp_tableau[i], tmp_tableau_element_list[i], x, y, dx, dy))
}
var tmp_stock_stack = new Stack();
var length = this.#deck.getSize();
//initialise the stock pile
for (var k=0; k < length; k++){
tmp_stock_stack.push(this.#deck.drawCard());
}
this.#stock_pile = new StockView(tmp_stock_stack, false);
this.#waste_pile = new WasteView();
this.#foundations = new FoundationView();
}
switch_deck_view(){ switch_deck_view(){
} }
draw_stock(){
var card = this.#stock_pile.draw();
console.log(card)
var retlist = this.#waste_pile.add(card, this.#scale_modifier);
if(retlist){
this.#stock_pile.on_receive(retlist);
}
}
reset(){
var tmp_view = [new View([new Background()])];
this.init_views();
this.#mgr.set_view(tmp_view.concat(this.#tableau, this.#stock_pile, this.#foundations, this.#waste_pile));
}
} }