Created
April 23, 2013 05:50
-
-
Save dermotbalson/5441112 to your computer and use it in GitHub Desktop.
poker hand
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--# Main | |
-- Main | |
-- Use this function to perform your initial setup | |
function setup() | |
--b=Backup("Cards v105") | |
img=readImage("Small World:Watch Tower") --image for back of card | |
dealPokerHand() | |
print("Touch the screen to redeal the hand") | |
end | |
function touched(touch) | |
dealPokerHand() --redeal if we touch the screen | |
end | |
function dealPokerHand() | |
c=Card(250,img) --big cards | |
p=Pack(1) | |
cards={} | |
for i=1,5 do | |
cards[i]=p:nextCard() | |
end | |
end | |
-- This function gets called once every frame | |
function draw() | |
background(69, 146, 59, 255) | |
--draw our hand of cards | |
--spread out cards to look nice | |
for i,card in ipairs(cards) do | |
c:draw(350+i*18,500,card.cardIndex,true,35-13*i) | |
end | |
--draw a pack face down | |
for i=1,4 do | |
c:draw(75+i*2,500-i*2,1,false) | |
end | |
end | |
--# Card | |
Card = class() | |
--[[ | |
this class builds and draws the card images from scratch and provides some utilities | |
--]] | |
--class initialises by creating card design | |
--Parameters: | |
--height of card in pixels | |
--the image to be used on the back | |
--background color on the face of the card | |
--(optional) background color on the back of the card | |
-- (optional) color along the border ofthe card | |
--returns nothing | |
function Card:init(height,backImg,faceColor,backColor,borderColor) | |
self.height = height | |
self.backImg=backImg | |
self.f=height/200 --scale font size to card size | |
self.faceColor=faceColor or color(255) | |
local x=100 --default border color | |
self.borderColor=borderColor or color(x, x, x, 255) | |
x=x*1.5 --corners are drawn with circles which appear darker than lines, so lighten colour for them | |
self.cornerColor=borderColor or color(x,x,x, 150) | |
self.backColor=backColor or color(154, 199, 203, 255) | |
self:createCard() | |
self:createSuits() | |
self.value={"A","2","3","4","5","6","7","8","9","10","J","Q","K"} | |
self.suit={"S","H","D","C"} | |
end | |
--this and the next function build just the front and back of the card itself | |
--the main problem is rounded corners | |
--this is done by drawing circles at the corners and then overlapping rectangles forthe final effect | |
function Card:createCard() | |
self.cardFace=self:createOutline(true) | |
self.cardBack=self:createOutline(false) | |
end | |
function Card:createOutline(face) | |
--use standard 25/35 ratio | |
self.width=math.floor(self.height*25/35+.5) | |
local img=image(self.width,self.height) | |
--create rounded corner on top right | |
local corner=0.05 --distance from end of card as percent of height | |
local c=math.floor(corner*self.height+0.5) | |
setContext(img) | |
pushStyle() | |
strokeWidth(1) | |
stroke(self.cornerColor) | |
--set background colour | |
if face then fill(self.faceColor) else fill(self.backColor) end | |
--draw small circles at corners | |
ellipse(self.width-c+1,self.height-c+1,c*2) | |
ellipse(self.width-c+1,c-1,c*2) | |
ellipse(c-1,self.height-c+1,c*2) | |
ellipse(c-1,c-1,c*2) | |
if face then stroke(self.faceColor) else stroke(self.backColor) end | |
--now rectangles to fill in thre centre of the card | |
rect(0,c,self.width,self.height-c*2) | |
rect(c,0,self.width-c*2,self.height) | |
--now a border round the card | |
stroke(self.borderColor) | |
line(0,c,0,self.height-c) | |
line(c,0,self.width-c,0) | |
line(self.width,c,self.width,self.height-c) | |
line(c,self.height,self.width-c,self.height) | |
--do picture on back | |
if face~=true then | |
sprite(self.backImg,img.width/2,img.height/2,img.width*.9) | |
end | |
popStyle() | |
setContext() | |
return img | |
end | |
--the suit images come from emoji | |
function Card:createSuits() | |
font("AppleColorEmoji") | |
self.suits={unicode2UTF8(9824),unicode2UTF8(9829),unicode2UTF8(9830),unicode2UTF8(9827)} | |
end | |
--draws a card at x,y with value of card (1-52), face=true if face up, a=angle in degrees (default 0) | |
function Card:draw(x,y,card,face,a) | |
pushMatrix() | |
translate(x+self.width/2,y-self.height/2) | |
if a==nil then a=0 end | |
rotate(a) | |
if face then | |
if card>0 then self:drawDetails(card) else sprite(self.cardFace,0,0) end | |
else | |
sprite(self.cardBack,0,0) | |
end | |
popMatrix() | |
end | |
--draws the numbers and symbols on the front of the card | |
--one parameter = card value | |
function Card:drawDetails(card) | |
sprite(self.cardFace,0,0) | |
pushStyle() | |
font("SourceSansPro-Regular") | |
fontSize(24*self.f) | |
--calculate suit and value of card | |
card=card-1 | |
local v=card%13 | |
local s=(card-v)/13+1 | |
v=v+1 | |
local w=self.cardFace.width | |
local h=self.cardFace.height | |
if s==1 or s==4 then fill(0,0, 0, 255) else fill(255,0,0,255) end --fill is red or black | |
--half the images on a card are upside down | |
--so we do them in two loops, turning the card upside down between them | |
--where the card is not exactly symmetrical, eg for odd numbers, we only draw on the first loop | |
for i=1,2 do | |
if i==2 then rotate(180) end --turn 180 degrees to do second loop | |
local u=self.suits[s] | |
text(self.value[v],-w*.4,h*.4) --text in corner of card | |
fontSize(16*self.f) | |
text(u,-w*.4,h*.28) --suit image | |
fontSize(28*self.f) | |
local ss=.13*h | |
--now all the symbols arranged in the middle of the card | |
if v==1 then | |
if i==1 then text(u,0,0) end | |
elseif v==2 then | |
text(u,0,.3*h) | |
elseif v==3 then | |
if i==1 then text(u,0,0) end | |
text(u,0,.3*h) | |
elseif v==4 then | |
text(u,-w*.18,.15*h) | |
text(u,w*.18,.15*h) | |
elseif v==5 then | |
text(u,-w*.18,.3*h) | |
text(u,w*.18,.3*h) | |
if i==1 then text(u,0,0) end | |
elseif v==6 then | |
text(u,-w*.18,.3*h) | |
text(u,w*.18,.3*h) | |
text(u,-w*.18,0) | |
elseif v==7 then | |
text(u,-w*.18,.3*h) | |
text(u,w*.18,.3*h) | |
text(u,-w*.18,0) | |
if i==1 then text(u,0,.15*h) end | |
elseif v==8 then | |
text(u,-w*.18,.3*h) | |
text(u,w*.18,.3*h) | |
text(u,-w*.18,0) | |
text(u,0,.15*h) | |
elseif v==9 then | |
text(u,-w*.18,.3*h) | |
text(u,w*.18,.3*h) | |
if i==1 then text(u,0,0) end | |
text(u,-w*.18,.1*h) | |
text(u,w*.18,.1*h) | |
elseif v==10 then | |
text(u,-w*.18,.3*h) | |
text(u,w*.18,.3*h) | |
text(u,-w*.18,.1*h) | |
text(u,w*.18,.1*h) | |
text(u,0,.2*h) | |
else --royalty | |
pushStyle() | |
font("AppleColorEmoji") | |
fill(255) | |
fontSize(84*self.f) | |
if i==1 then | |
if v==11 then text(unicode2UTF8(128113)) | |
elseif v==12 then text(unicode2UTF8(128120)) | |
else text(unicode2UTF8(128116)) | |
end | |
end | |
popStyle() | |
end | |
end | |
popStyle() | |
end | |
--used by Main and other classes | |
--given a value 1-52, it returns the value and suit in text and numbers, eg S,J,1,11 | |
function Card:SuitValue(c) | |
local v=(c-1)%13 | |
local s=(c-1-v)/13+1 | |
v = v + 1 | |
return self.value[v],self.suit[s],v,s | |
end | |
function unicode2UTF8(u) --needed for emoji | |
u = math.max(0, math.floor(u)) -- A positive integer | |
local UTF8 | |
if u < 0x80 then -- less than 8 bits | |
UTF8 = string.char(u) | |
elseif u < 0x800 then -- less than 12 bits | |
local b2 = u % 0x40 + 0x80 | |
local b1 = math.floor(u/0x40) + 0xC0 | |
UTF8 = string.char(b1, b2) | |
elseif u < 0x10000 then -- less than 16 bits | |
local b3 = u % 0x40 + 0x80 | |
local b2 = math.floor(u/0x40) % 0x40 + 0x80 | |
local b1 = math.floor(u/0x1000) + 0xE0 | |
UTF8 = string.char(b1, b2, b3) | |
elseif u < 0x200000 then -- less than 22 bits | |
local b4 = u % 0x40 + 0x80 | |
local b3 = math.floor(u/0x40) % 0x40 + 0x80 | |
local b2 = math.floor(u/0x1000) % 0x40 + 0x80 | |
local b1 = math.floor(u/0x40000) + 0xF0 | |
UTF8 = string.char(b1, b2, b3, b4) | |
elseif u < 0x800000 then -- less than 24 bits | |
local b5 = u % 0x40 + 0x80 | |
local b4 = math.floor(u/0x40) % 0x40 + 0x80 | |
local b3 = math.floor(u/0x1000) % 0x40 + 0x80 | |
local b2 = math.floor(u/0x40000) % 0x40 + 0x80 | |
local b1 = math.floor(u/0x1000000) + 0xF8 | |
UTF8 = string.char(b1, b2, b3, b4, b5) | |
else | |
print("Error: Code point too large for Codea's Lua.") | |
end | |
return UTF8 | |
end | |
--# Pack | |
Pack = class() | |
--[[ | |
Manages one or more packs of cards | |
Functions: | |
shuffle - shuffles the pack | |
nextCard - returns the next card in the pack | |
--]] | |
function Pack:init(p) | |
self.pack=self:shuffle(p) | |
end | |
function Pack:shuffle(p) | |
n=p or 1 --number of packs, defaults to 1 | |
--set up pile with all the packs in order first | |
local t={} | |
for i=1,n do | |
for j=1,52 do | |
t[#t+1]=j | |
end | |
end | |
--now sort the pile randomly by pulling cards out at random | |
local pack={} --table to hold shuffled cards | |
while #t>0 do | |
local i=math.random(1,#t) | |
pack[#pack+1]=t[i] | |
table.remove(t,i) | |
end | |
return pack | |
end | |
function Pack:nextCard(p) | |
if #self.pack==0 then return nil end | |
local value={"A","2","3","4","5","6","7","8","9","10","J","Q","K"} | |
local suit={"S","H","D","C"} | |
local c=self.pack[1] | |
table.remove(self.pack,1) | |
local v=(c-1)%13+1 | |
local s=(c-v)/13+1 | |
return {value=value[v],suit=suit[s],valueIndex=v,suitIndex=s,cardIndex=c} | |
end | |
function Pack:cards() | |
return #self.pack | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment