# Using Graphics... for Simple Games.

This lesson is the first in a series which illustrates a very simple card game. All you can do here, is 'draw' a card from a dealt hand of four cards. The 'puter then draws it's own card from the deck, and the higher card wins.

In this first example, you have to use the number keys to select a card. The 'mouse' selection will have to wait until the next lesson.

To keep things small, my deck actually only has five cards. The image information is stored in a pixmap, which contains a 'combined' bitmap of the five cards, and a card 'back'.

In this particular bitmap, ( cardtrix.bmp ), I've even gone to the trouble of overlapping the card borders, to keep it a bit smaller.

Indexing into this combined bitmap is quite simple. Since the cards are all 71 by 98 pixels in size, we just use an 'x' value of 70, because the borders overlap. The first card-back image in the bitmap starts at '0 times 70', and the next ( first card ) at '1 times 70'. Since the cards in the bitmap are in order, our card values for this simple game are also in order.

Game programming, naturally, is event driven, so I'm using a couple of timers to determine what happens when.
The first timer is used to add a bit of delay at the beginning of the game, and after every play, before the 'hand' is dealt out on the screen. It's also used as a 'trigger' to invoke the next round.

The second timer is used as a delay, to determine when the player can enter a selection. Any user input that takes place before this timer has timed out will be ignored, since the 'ready' flag hasn't been set yet.

A simple call to Euphoria's sleep() routine is used to time the dealing process, and a few others.

-- card-trix-1.exw

    include win32lib.ew
    without warning

    sequence deck, cards

    -- the 'values' of the cards in the deck,
    -- and their 'index' into the deck's pixmap.
    deck = {1,2,3,4,5}

    -- and, their names, to be used in the status bar 'window'.
    cards = {"Ten","Jack","Queen","King","Ace"}

    -- the game variables,
    integer ready, picked, myscore, yourscore
    ready = 0
    myscore=0
    yourscore=0

    ----

    constant
    -- messages to be posted in the status bar.
    msg0 = "...dealing cards.",
    msg1 = "...draw a card ( 1 to 4 )",
    msg2 = "You Lose :)",
    msg3 = "You Win !!",

    MyWin   = create( Window, "Card-Trix-1", 0, 10, 10, 300, 320, 0 ),
    yours   = create( LText, "You", MyWin, 5, 10, 100, 20, 0 ),
    mine    = create( RText, "Me", MyWin, 180, 10, 100, 20, 0 ),
    menuBar = create( Menu, "&Program", MyWin, 0, 0, 0, 0, 0 ),
    menuOut = create( MenuItem, "E&xit", menuBar, 0, 0, 0, 0, 0 ),
    statBar = create( StatusBar, "", MyWin, 0, 0, 0, 0, 0 ),

    -- our whole deck goes in this,
    deckPix = create( Pixmap, "", 0, 0, 0, 421, 71, 0 ),
    -- the 'dealt' hand goes in here,
    dealPix = create( Pixmap, "", 0, 0, 0, 131, 98, 0 ),
    -- and our selected cards go in here
    playPix = create( Pixmap, "", 0, 0, 0, 149, 98, 0 ),

    myTimer = 1,
    myTimer2 = 2

    ----

    -- set up some parameters, and fetch the bitmap,
    -- from our '.\Bin' sub-folder.
    setWindowBackColor(MyWin,Green)
    setFont(yours,"System",0,0)
    setFont(mine,"System",0,0)
    setPixmap( deckPix, loadBitmapFromFile(".\\Bin\\cardtrix.bmp") )

    ----

    -- this shuffles our card sequence.
    function shuffle(sequence s)
    integer r
    object temp
      for i = length(s) to 1 by -1 do
        r = rand(i)
        temp = s[r]
        s[r] = s[i]
        s[i] = temp
      end for
      return s
    end function

    ----

    -- this re-paints our pixmaps, and copies them
    -- to our client window, to 'refresh' the display.
    procedure green()
      setPenColor(dealPix,Green)
      drawRectangle(dealPix,1,0,0,131,98)
      copyBlt(MyWin,80,140,dealPix)
      setPenColor(playPix,Green)
      drawRectangle(playPix,1,0,0,149,98)
      copyBlt(MyWin,70,35,playPix)
    end procedure

    ----

    -- this function lets the 'puter select any card,
    -- except the one we've already chosen.
    function anything_but(integer x)
    integer r
      r = rand( 3 )
      if r >= x then r += 1 end if
      return r
    end function

    ----

    procedure play(integer picked)
    integer pos, rnd, you, me
      if ready = 1 then
        ready = 0
        setText(statBar,"...you drew the " & cards[deck[picked]])
        you = deck[picked]
        pos = deck[(picked)]*70
        bitBlt(playPix,0,0,deckPix,pos,0,71,98,SrcCopy)
        copyBlt(MyWin,70,35,playPix)
        sleep(1)
        rnd = anything_but(picked)
        me = deck[rnd]
        pos = deck[rnd]*70
        bitBlt(playPix,78,0,deckPix,pos,0,71,98,SrcCopy)
        copyBlt(MyWin,70,35,playPix)
        sleep(2)

        -- the following routine just adds up the score.
        if me > you then
          setText(statBar,msg2)
          myscore += 1
          setText(mine,"Me " & sprintf("%d",myscore) )
        else
          setText(statBar,msg3)
          yourscore += 1
          setText(yours,"You " & sprintf("%d",yourscore) )
        end if
    ---
        sleep(3) -- give user time to see what's going on,
        green()  -- before 'greening' the pixmaps,etc.
        deck = shuffle(deck)  -- then shuffle the deck
        setTimer(MyWin,myTimer,500) -- and set the re-start 'trigger'.
      end if
    end procedure

    ----

    procedure start_up(atom self, atom event, sequence params)
      green()
      deck = shuffle(deck)
      setText(statBar,msg0)
      setTimer(MyWin,myTimer,500)
    end procedure
    --
    setHandler( MyWin, w32HOpen, routine_id("start_up") )

    ----

    procedure do_deal(atom self, atom event, sequence params)
        atom timerId = params[1]

        if timerId = 1 then
            killTimer(MyWin,myTimer)
            setTimer(MyWin,myTimer2,3500)
            setText(statBar,msg0)
            for i = 0 to 3 do
                bitBlt(dealPix,i*20,0,deckPix,0,0,71,98,SrcCopy)
                copyBlt(MyWin,80,140,dealPix)
                sleep(1)
            end for
        elsif timerId = 2 then
            killTimer(MyWin,myTimer2)
            ready = 1
            setText(statBar,msg1)
        end if

    end procedure
    --
    setHandler( MyWin, w32HTimer, routine_id("do_deal") )

    ----

    -- this 'filters' and converts keyboard input into a numeric value
    -- and passes on to the play routine.
    procedure pick(atom self, atom event, sequence params)
      atom key = params[1]
      if key > 48 and key < 53 then
        picked = key - 48
        play(picked)
      end if
    end procedure
    setHandler( MyWin, w32HKeyDown, routine_id("pick") )

    ----

    procedure quit(atom self, atom event, sequence params)
      closeWindow( MyWin )
    end procedure
    setHandler( menuOut, w32HClick, routine_id("quit") )

    ----

    WinMain( MyWin, Normal )

    ----

When you play around with this program, you'll notice it has a lot of shortcomings. Trying to exit from the program, 'dragging' its window, or even accessing it's menu while it's drawing to the screen, or 'sleeping' won't work, etc. Some of these issues will be addressed in the next few examples, but first let's make this a 'mouse-able' program.

..end of lesson.

CONTENTS