--************************************************************************************************* CARDW = 200 CARDH = 300 Heart = 1 Spade = 2 Diamond = 3 Club = 4 FaceUp = true FaceDown = false backId = 54 TABLEAU_MARGIN_FACEUP = 80 TABLEAU_MARGIN_FACEDOWN = 10 --************************************************************************************************* local lgni = love.graphics.newImage local lgnq = love.graphics.newQuad local lsgsc = love.graphics.setColor local lgd = love.graphics.draw local lgsc = love.graphics.setColor local lgr = love.graphics.rectangle --************************************************************************************************* local cardAtlas = lgni("deck52english.png") local cardAtlasW = cardAtlas:getWidth() local cardAtlasH = cardAtlas:getHeight() local cardQuads = {} for i = 1, 57 do cardQuads[i] = lgnq(((i-1) % 13) * CARDW, math.floor((i-1) / 13) * CARDH, CARDW, CARDH, cardAtlasW, cardAtlasH) end --************************************************************************************************* local Card = { id = 1, x = 0, y = 0, w = CARDW, h = CARDH } function Card:show() self.showing = FaceUp end function Card:move(x, y) self.x = x self.y = y end function Card:hitTest(x, y) return not ( (x < self.x) or (x > (self.x + self.w)) or (y < self.y) or (y > (self.y + self.h)) ) end function Card:draw() lgsc(1, 1, 1, 1) if (self.showing == FaceUp) then lgd(cardAtlas, cardQuads[self.id], self.x, self.y) else lgd(cardAtlas, cardQuads[backId], self.x, self.y) end lgsc(0.25, 0.25, 0.25, 1) lgr("line", self.x, self.y, CARDW, CARDH, 4) end function Card:new(id, x, y, showing) local o = {} for k, v in pairs(self) do o[k] = v end o.id = id o.rank = math.floor(((id - 1) % 13) + 1); o.suit = math.floor(((id - 1) / 13) + 1); o.showing = showing return o end --************************************************************************************************* local Deck = { x = 0, y = 0 } function Deck:empty() local j = #self for i = 1, j do self[i] = nil end end function Deck:push(card) card.owner = self card.x = self.x card.y = self.y self[#self + 1] = card end function Deck:layout() if (self.tableau) then local yoff = self.y for _, card in ipairs(self) do card.x = self.x card.y = yoff yoff = yoff + ((card.showing == FaceUp) and TABLEAU_MARGIN_FACEUP or TABLEAU_MARGIN_FACEDOWN) end else for _, card in ipairs(self) do card.x = self.x card.y = self.y end end end --Fisher–Yates shuffle. function Deck:shuffle() for i = #self-1, 1, -1 do j = math.random(0, i) local tc = self[i+1] self[i+1] = self[j+1] self[j+1] = tc end end function Deck:move(x, y) self.x = x self.y = y for _, card in ipairs(self) do card.x = x card.y = y end self:layout() end function Deck:findCardUnderMouse(x, y) if (#self == 0) then return end for i = #self, 1, -1 do local card = self[i] if (card:hitTest(x, y)) then return card end end end function Deck:hitTest(x, y) return not ( (x < self.x) or (x > (self.x + self.w)) or (y < self.y) or (y > (self.y + self.h)) ) end function Deck:indexOf(card) if (#self == 0) then return end for i = #self, 1, -1 do if (card == self[i]) then return #self - i end end return math.huge end function Deck:draw() if (#self == 0) then lgsc(1, 1, 0, 1) lgr("line", self.x, self.y, self.w, self.h, 15) else for _, card in ipairs(self) do card:draw() end end end function Deck:topCard() return self[#self] end function Deck:pop() local o = self[#self] self[#self] = nil return o end function Deck:popAt(atCard) if (#self == 0) then return end local deck = Deck:new(mx, my, true); local count = #self for i = 1, count do if (self[i] == atCard) then for j = i, count do deck:push(self[j]) self[j] = nil end break end end return deck end function Deck:new(x, y, tableau, cards) local o = {} for k, v in pairs(self) do o[k] = v end o.x = x or 0 o.y = y or 0 o.w = CARDW o.h = CARDH o.tableau = tableau if (cards) then for _, card in ipairs(cards) do o:push(card) end end return o end --************************************************************************************************* return Deck, Card