Thak
Quick Links
Game Concept
Game Specifics
Networking Functions (Mike Del Giudice)
Gameplay Functions (Dan Mueller, all)
Graphics Functions (Matt Wood)
Sound Functions (Tim Zadigian)
ScreenShots
Contact

Game Concept
 

    "Thak" revolves around our central character, namely a caveman named Thak (imagine that).  The game itself is an overhead, real-time strategy game, similar to that of the Command and Conquer, StarCraft genre.  Each player begins the game controlling Thak, and a hut where cavemen can be trained.  Thak himself is not a warrior.  He builds things.  Warriors carry clubs and they do all the attacking.  Thak can build walls.  A player can command up to five cavemen at a time, and cavemen can be replaced as they are eliminated. 
   The objective of the game is to protect Thak and kill the other player's Thak.  There is no mining in this game, so to speak.  You don't collect resources. 

   We implemented all of our original programming goals, as listed below. Due to time constraints, however, we were unable to explore our optional programming goals. We are quite happy to say, though, that the game is fully functional and playable.
We intended to develop Thak as a multiplayer game, so networking support is included using the NetLib functions provided by John Lockwood, professor of ECE 291..



Main Programming Goals of "Thak": ALL ACCOMPLISHED Possible Programming Goals, if Above were Completed Early We maintained all of our original ideas, because we all agreed we'd like to make something we might actually come back to and appreciate outside of the class (maybe even use at a later time, whoa).

Known Bugs in Thak as of handin date, December 8, 1998:
    -producing 5th caveman sometimes causes opponent to lock up.
    -Occasional screen flicker seems to make cavemen disappear for short periods of time.  May be due to net lag.
    -Thak always exits building wall to the upper left, occasionally overstepping collision detection.

game specs

General Network Structure

server diagram
 
 
The first player to log in creates an instance of "ThakTheServer." This player is assigned player number 0, which is equivalent to being player one.  The second player is then, naturally player two, and is assigned player number 1.  Each player broadcasts the packet containing their player structure.  Upon receiving a packet, the client checks the player number who sent it (first byte in packet).  If it is his own packet, it is discarded.  If it is the opposing player, it is stored in the OtherUnits structure.  The client only accepts packets from his specific opponent. At this point the clients enter the main game loop, in which they: 
     1) Receive Packet from the server. 
     2) Check if Thak is alive.  If he's not, the game is over and we jump to the game over sequence. 
     3) Client draws the screen. 
     4) Clients create new units and buildings. 
     5) Client moves his existing units. 
     6) If units were attacked health is updated, as are caveman statuses. 
     7) Each client updates his unit structure. 
     8) Sounds are played. 
     9) Each client broadcasts their unit structure.. 
    10) Loops back to 1)
The Game grid will be consist of 440 blocks, each 30 pixels high and 30 pixels wide.  Therefore the entire game space will occupy 660x600 pixels.  This game grid will be mapped to a minimap four times as large (88x80) in the control panel on the bottom of the screen.  This minimap will contain colored pixels, red representing a block occupied by the current player, blue a block occupied by his opponent, green representing grass, brown representing walls,  and gray representing rocks.

game gridgrid word

Each double word in the game grid is constructed as shown above.
The first byte represents the type of terrain.
  (0=hut, 3=grass, 4=wall, 5=rock)
The next byte represents the status of that object.
  (Applied to wall to determine which corner).
The next byte was used to  represent the health of the wall,
but was later eliminated as we removed the ability to attack walls.
The last byte is not used.
 
 
 

CONSTANTS (on both Server and Client)

Variables (on Server)
    ;Structures
            UnitStructure    STRUC
                Type    db     ?    ;unit type   0=Thak 1=Caveman    2=Hut    3=Wall
                Status   db    ?    ;Status indicator i.e. player direction, digger position If = 0FFh, indicates unit doesn't exist.
                PosX    dw    ?    ;X coordinate of this unit
                PosY    dw    ?    ;Y coordinate of this unit
                Health   db    ?    ;Health of this unit
                CurrentG    dw    ?    ;Current grid position of this unit
                DestinationG    dw    ?    ;destination grid position for this unit.
            ENDS
            P1Units    STRUC
                PlayerNumber    db    1
                Hut    UnitStructure  <2,0,HUT1XSTART,HUT1YSTART,HUTHEALTH,HUT1GRIDSTART,
                                                  HUT1GRIDSTART>
                Thak    UnitStructure    <0,2,THAK1XSTART,THAK1YSTART,THAKHEALTH,THAK1GRIDSTART,
                                                      THAK1GRIDSTART>
                Caveman0 UnitStructure <1,0FFh,0,0,0,0,0>
                Caveman1 UnitStructure <1,0FFh,0,0,0,0,0>
                Caveman2 UnitStructure <1,0FFh,0,0,0,0,0>
                Caveman3 UnitStructure <1,0FFh,0,0,0,0,0>
                Caveman4 UnitStructure <1,0FFh,0,0,0,0,0>
                NewWall   UnitStructure <3,0FFh,0,0,0,0,0>    ;indicates a new wall has been created and where, if needed.
            ENDS
            P2Units    STRUC
                PlayerNumber     db    2
                Hut    UnitStructure    <2,0,HUT2XSTART,HUT2YSTART,HUTHEALTH,HUT2GRIDSTART,
                                                  HUT2GRIDSTART>
                Thak    UnitStructure    <0,2,THAKXSTART,THAKYSTART,THAKHEALTH,THAK2GRIDSTART,
                                                      THAK2GRIDSTART>
                Caveman0 UnitStructure <1,0FFh,0,0,0,0,0>
                Caveman1 UnitStructure <1,0FFh,0,0,0,0,0>
                Caveman2 UnitStructure <1,0FFh,0,0,0,0,0>
                Caveman3 UnitStructure <1,0FFh,0,0,0,0,0>
                Caveman4 UnitStructure <1,0FFh,0,0,0,0,0>
                NewWall   UnitStructure <3,0FFh,0,0,0,0,0>    ;indicates a new wall has been created and where, if needed.
            ENDS

Variables (on Client)

   ;Segments
        WAVSeg segment 'DATA1'        ;segment holds wave data
                WaveBuffer DB 65535 dup(?)
        WAVSeg ends
 

        MIDISeg segment 'DATA2'        ;segment holds midi data
                MIDIBuffer db 65535 dup(?)
        MIDISeg ends
 

        SBSeg segment 'DATA3'      ;segment holds screen data
                ScreenBuffer db 65535 dup(?) ;blasted from here to the screen
        SBSeg ends
 

        FontSeg segment 'DATA4'   ;used by load pcx holds the fontmap (like in mp4)
                FontMap db 65535 dup(?)
        FontSeg ends
 

        SCRSeg segment 'DATA5'              ;used by load PCX holds files while
                Scratchpad db 65535 dup(?)   ;they are decoded
        SCRSeg ends
 

        DrawSeg segment 'DATA6'     ;holds map for things to draw
                DrawMap db 65535 dup(?) ; buildings units terraine
        DrawSeg ends
 

        StarSeg segment 'DATA7'              ;holds Star field for intro
                StarMap db 65535 dup(?)
        StarSeg ends

DrawFile        db 'units2.pcx',0  ;filename of PCX file with building images.
CBarFile        db 'Cbarmap.pcx',0 ;filename of PCX file with control bar images.
MainMenuFile    db 'mainmenu.pcx',0 ;filename of MainMenu PCX file
Inst1File       db 'Inst1.pcx',0  ;instruction one file
Inst2File       db 'Inst2.pcx',0   ;instruction two file
WaitFile        db 'waiting.pcx',0 ;waiting file
Fire1File       db 'fire1.pcx',0  ;Fire1 anim
Fire2File       db 'fire2.pcx',0  ;Fire2 anim
Fire3File       db 'fire3.pcx',0  ;Fire3 anim
StarsFile       db 'stars.pcx',0  ;Star field
Head1File       db 'Head1.pcx',0
Head2File       db 'Head2.pcx',0
Head3File       db 'Head3.pcx',0
Head4File       db 'Head4.pcx',0  ;Head 4 file
Head5File       db 'Head5.pcx',0  ;Head 5 file
Head6File       db 'Head6.pcx',0  ;Head 6 file
ThakFile        db 'thak.pcx',0   ;Thak

;NOTE: also need variables with filenames for .WAV files and MIDI files
;(for MIDPAK).

; FontMap is a 320x200 PCX File containing 8x8 letters
; ABCDEFGHIJKLMNOPQRSTUVWXYZ
; abcdefghijklmnopqrstuvwxyz
; 01234567890
;
; Letters is a 256-word lookup table that
; maps each ASCII value to a location in FontMap
; Our program need only map letters, digits, space, and period.
; As used in MP4.

Letters dw      32 dup ((320*166)+(8*11))
        dw      (320*166)+(8*12) ; ' '
        dw      13 dup ((320*166)+(8*11))
        dw      (320*166)+(8*10) ; '.'
        dw      (320*166)+(8*11)
        dw      (320*166)+(8*0)  ; '0'
        dw      (320*166)+(8*1)  ; '1'
        dw      (320*166)+(8*2)  ; '2'
        dw      (320*166)+(8*3)  ; '3'
        dw      (320*166)+(8*4)  ; '4'
        dw      (320*166)+(8*5)  ; '5'
        dw      (320*166)+(8*6)  ; '6'
        dw      (320*166)+(8*7)  ; '7'
        dw      (320*166)+(8*8)  ; '8'
        dw      (320*166)+(8*9)  ; '9'
        dw      7 dup ((320*166)+(8*11))
        dw      (320*150)+(8*0)   ; 'A'
        dw      (320*150)+(8*1)   ; 'B'
        dw      (320*150)+(8*2)   ; 'C'
        dw      (320*150)+(8*3)   ; 'D'
        dw      (320*150)+(8*4)   ; 'E'
        dw      (320*150)+(8*5)   ; 'F'
        dw      (320*150)+(8*6)   ; 'G'
        dw      (320*150)+(8*7)   ; 'H'
        dw      (320*150)+(8*8)   ; 'I'
        dw      (320*150)+(8*9)   ; 'J'
        dw      (320*150)+(8*10)  ; 'K'
        dw      (320*150)+(8*11)  ; 'L'
        dw      (320*150)+(8*12)  ; 'M'
        dw      (320*150)+(8*13)  ; 'N'
        dw      (320*150)+(8*14)  ; 'O'
        dw      (320*150)+(8*15)  ; 'P'
        dw      (320*150)+(8*16)  ; 'Q'
        dw      (320*150)+(8*17)  ; 'R'
        dw      (320*150)+(8*18)  ; 'S'
        dw      (320*150)+(8*19)  ; 'T'
        dw      (320*150)+(8*20)  ; 'U'
        dw      (320*150)+(8*21)  ; 'V'
        dw      (320*150)+(8*22)  ; 'W'
        dw      (320*150)+(8*23)  ; 'X'
        dw      (320*150)+(8*24)  ; 'Y'
        dw      (320*150)+(8*25)  ; 'Z'
        dw      6 dup ((320*166)+(8*11))
        dw      (320*158)+(8*0)   ; 'a'
        dw      (320*158)+(8*1)   ; 'b'
        dw      (320*158)+(8*2)   ; 'c'
        dw      (320*158)+(8*3)   ; 'd'
        dw      (320*158)+(8*4)   ; 'e'
        dw      (320*158)+(8*5)   ; 'f'
        dw      (320*158)+(8*6)   ; 'g'
        dw      (320*158)+(8*7)   ; 'h'
        dw      (320*158)+(8*8)   ; 'i'
        dw      (320*158)+(8*9)   ; 'j'
        dw      (320*158)+(8*10)  ; 'k'
        dw      (320*158)+(8*11)  ; 'l'
        dw      (320*158)+(8*12)  ; 'm'
        dw      (320*158)+(8*13)  ; 'n'
        dw      (320*158)+(8*14)  ; 'o'
        dw      (320*158)+(8*15)  ; 'p'
        dw      (320*158)+(8*16)  ; 'q'
        dw      (320*158)+(8*17)  ; 'r'
        dw      (320*158)+(8*18)  ; 's'
        dw      (320*158)+(8*19)  ; 't'
        dw      (320*158)+(8*20)  ; 'u'
        dw      (320*158)+(8*21)  ; 'v'
        dw      (320*158)+(8*22)  ; 'w'
        dw      (320*158)+(8*23)  ; 'x'
        dw      (320*158)+(8*24)  ; 'y'
        dw      (320*158)+(8*25)  ; 'z'
        dw      132 dup ((320*166)+(8*11))

Units   dw      (320*0)+(30*0)  ;position of caveman up, position one (CU1)
        dw      (320*0)+(30*1)  ;CR1
        dw      (320*0)+(30*2)  ;CD1
        dw      (320*0)+(30*3)  ;CL1
        dw      (320*0)+(30*4)  ;CU2
        dw      (320*0)+(30*5)  ;CR2
        dw      (320*0)+(30*6)  ;CD2
        dw      (320*0)+(30*7)  ;CL2
        dw      (320*0)+(30*8)  ;position of caveman attack position up (CAU)
        dw      (320*0)+(30*9)  ;CAR
        dw      (320*30)+(30*0) ;CAD
        dw      (320*30)+(30*1) ;CAL
        dw      (320*30)+(30*2) ;position of thak up, position one (TU1)

        dw      (320*30)+(30*3) ;TR1
        dw      (320*30)+(30*4) ;TD1
        dw      (320*30)+(30*5) ;TL1
        dw      (320*30)+(30*6) ;TU2
        dw      (320*30)+(30*7) ;TR2
        dw      (320*30)+(30*8) ;TD2
        dw      (320*30)+(30*9) ;TL2
        dw      (320*60)+(30*0) ;Location of Digger animated position one
        dw      (320*60)+(30*2) ;Location of Digger animated position two
        dw      (320*60)+(60*2) ;Location of Hut
        dw      (320*60)+(60*3) ;Location of Wall, Top Left corner
        dw      (320*60)+(30*7) ;Top right corner
        dw      (320*90)+(60*3) ;Bot Left corner
        dw      (320*90)+(30*7) ;Bot Right corner

Terrain dw      (320*120)+(30*0) ;location of grass
        dw      (320*120)+(30*1) ;location of rock

CBarLetters  dw 65 dup ((320*174)+(8*26))
        dw      (320*174)+(8*0)   ; 'A' (letters for control bar)
        dw      (320*174)+(8*1)   ; 'B'
        dw      (320*174)+(8*2)   ; 'C'
        dw      (320*174)+(8*3)   ; 'D'
        dw      (320*174)+(8*4)   ; 'E'
        dw      (320*174)+(8*5)   ; 'F'
        dw      (320*174)+(8*6)   ; 'G'
        dw      (320*174)+(8*7)   ; 'H'
        dw      (320*174)+(8*8)   ; 'I'
        dw      (320*174)+(8*9)   ; 'J'
        dw      (320*174)+(8*10)  ; 'K'
        dw      (320*174)+(8*11)  ; 'L'
        dw      (320*174)+(8*12)  ; 'M'
        dw      (320*174)+(8*13)  ; 'N'
        dw      (320*174)+(8*14)  ; 'O'
        dw      (320*174)+(8*15)  ; 'P'
        dw      (320*174)+(8*16)  ; 'Q'
        dw      (320*174)+(8*17)  ; 'R'
        dw      (320*174)+(8*18)  ; 'S'
        dw      (320*174)+(8*19)  ; 'T'
        dw      (320*174)+(8*20)  ; 'U'
        dw      (320*174)+(8*21)  ; 'V'
        dw      (320*174)+(8*22)  ; 'W'
        dw      (320*174)+(8*23)  ; 'X'
        dw      (320*174)+(8*24)  ; 'Y'
        dw      (320*174)+(8*25)  ; 'Z'

UnitPortraits   dw   (320*5)+5       ;should never be used, 0 represents no unit selected.
        dw      (320*90)+(43*2) ;location of Hut portrait
        dw      (320*90)+(43*1)    ;location of Thak portrait
        dw      5 dup ((320*90)+(43*0))   ;location of Caveman portrait

UnitNames dw    (320*90)+(43*3)      ;never used.  0 reps no unit selected.
        dw      (320*111)+(43*3)     ;location of 'Hut'
        dw      (320*90)+(43*3)+93   ;location of 'Thak'
        dw      (320*90)+(43*3)      ;location of 'Caveman'

;Sound Variables
        ;DMA     db        1              ;contains DMA for sound
        ;IRQ     db        5              ;IRQ for sound
        ;Base    dw       220h            ;Base contains Port Address for sound
 
 
        crlf    db CR,LF,'$' ; DOS uses carriage return + Linefeed for new line
        CrashSound db      'hitface1.wav',0   ; Filename of crash sound
        WavLength       dw  0
        Sample  db      'tarzan1.wav',0
        Mario   db      'Mario.xmi',0
        MarioLength dw  11956
        island  db      'Isld.xmi',0
        isLn    dw      6384
 
        ;real midi vars
        MIDOne          db      'MIDOne.xmi', 0
        MIDOneLn        dw      13524
        MIDTwo          db      'MIDTwo.xmi', 0
        MIDTwoLn        dw      14890
        MIDThr          db      'MIDThr.xmi', 0
        MIDThrLn        dw      8524
        MIDFour         db      'MIDFour.xmi', 0
        MIDFourLn       dw      5870
        MIDFive         db      'MIDFive.xmi', 0
        MIDFiveLN       dw      1568
        MIDSix          db      'MIDSix.xmi', 0
        MIDSixLn        dw      15830
 
        ;real wav vars
        ThakDie         db      0                ;flags fo tell if a sound needs to be played
        NewDest         db      0
        BuildCrsh       db      0
        CvDie           db      0
        HutHit          db      0
        Hit             db      0
        NewCv           db      0
        ThakBld         db      0

 
        ThakDieSnd      db      'SomeFile.wav', 0
        NewDestSnd      db      'SomeFile.wav', 0
        BuildCrshSnd    db      'SomeFile.wav', 0
        CvDieSnd        db      'SomeFile.wav', 0
        HutHitSnd       db      'SomeFile.wav', 0
        HitSnd          db      'hitface1.wav', 0
        NewCvSnd        db      'SomeFile.wav', 0
        ThakBldSnd      db      'SomeFile.wav', 0
        CvSelSnd        db      'tarzan1.wav', 0
        ThakSelSnd      db      'tarzan1.wav', 0
        HutSelSnd       db      'SomeFile.wav', 0
        TapGlassSnd     db      'SomeFile.wav', 0
 
 

        ;sampling vars
        SampRate        db ?
        TtwoSamp        db 206
        ElevSamp        db 165
        EightSamp       db 131
 
        SAMPLING        db 0
 

;Graphics Variables
        ViewPortX    dw    0    ;X coordinate of current view screen.
        ViewPortY    dw    0    ;Y coordinate of current view screen.
        HutBurn      db    1

;Input Variables
        oldKeyV        dd    ?     ;holds old key and mouse handler addresses
        MouseX         dw    0     ;holds Mouse X and Y coordinates (in relation to current screen). 0 <= X <= 319
        MouseY         dw    0     ;0 <= Y <= 199
        LeftB          db    0     ;Flags to indicate if Left or Right mouse buttons have been clicked.
        RightB         db    0
        Ipressed       db    0     ;Flags to indicate different Keystrokes, set by Keyboard handler.
        Jpressed       db    0
        Mpressed       db    0
        Xpressed       db    0
        Uppressed      db    0
        Downpressed    db    0
        RightPressed   db    0
        LeftPressed    db    0
        EscPressed     db    0
        BPressed       db    0
        SpcPressed     db    0
;GamePlay Variables
        MyKills        dw    0            ;stores kills for this player
        MyLosses       dw    0            ;stores deaths for this player (equal to kills for other player)
        PlayerSelected db    0            ;indicates if a unit is selected, and if so, which one.1=Thak,2=Caveman0,etc. 0=none
                                ;0=none 1=Hut 2=Thak 3,4,5,6,7=Caveman0-4
        WallBuild      db    0            ;timer for construction of a wall.
        CavemanBuild   db    0            ;timer for creation of a caveman.
        CurrentGX      db    ?
        CurrentGY      db    ?
        DestinationGX  db    ?
        DestinationGY  db    ?
        StateTimer     db    0
        CavemanOffset  dw    0            ;offset of caveman which is being built

        GameGrid       dd       3h
                       dd       3h
                       dd       5
                       dd       19 dup (3)
                       dd       3h
                       dd       3h
                       ;dd       20 dup (3)  ;game grid recieved from server.
                       dd       80 dup (3)
                       dd       5
                       dd       120 dup (3)
                       dd       5
                       dd       50 dup (3)
                       dd       5
                       dd       30 dup (3)
                       dd       5
                       dd       72 dup (3)
                       dd       00000004h
                       dd       00000104h
                       dd       20 dup (3)
                       dd       00000304h
                       dd       00000204h
                       dd       3 dup (3)
                       dd       5
                       dd       34 dup (3)
 

;Structures
        UnitStructure    STRUCT
           UnitType     db    ?    ;unit type   0=Thak 1=Caveman 2=Hut 3=Wall
           Status       db    ?    ;Status indicator i.e. player direction, digger position
           PosX         dw    ?    ;X coordinate of this unit
           PosY         dw    ?    ;Y coordinate of this unit
           Health       db    ?    ;Health of this unit
           CurrentG     dw    ?    ;Current grid position of this unit
           DestinationG dw    ?    ;destination grid position for this unit.
        UnitStructure ENDS

        PlayerStructure STRUCT
           PlayerNumber    db    0FFh    ;contains 1 if player 1, 2 if player 2
           Hut      UnitStructure  <2,0,30,60,30,45,45>
           Thak     UnitStructure <0,02h,120,60,15,48,48>
           Caveman0 UnitStructure <1,0FFh,0,0,15,35,0>
           Caveman1 UnitStructure <1,0FFh,0,0,15,100,0>
           Caveman2 UnitStructure <1,0FFh,0,0,15,156,0>
           Caveman3 UnitStructure <1,0FFh,0,0,15,200,0>
           Caveman4 UnitStructure <1,0FFh,0,0,15,336,0>
           NewWall  UnitStructure <3,0FFh,0,0,0,0,0>    ;indicates a new wall has been created and where, if needed.
           GOver           db    0
       PlayerStructure ENDS

       MyUnits  PlayerStructure <>
       OtherUnits PlayerStructure <>
 

The Game Main Function (this is the pseudocode for our game main sequence)

GameMain
        CheckSound
        RegisterXMIDI
        InstThakKey
 LoadPCXFirst ;loads first image and sets palette
 Use LoadPCX to load fontmap and drawmap
         Display IntroSequence
MainMenu:
        GameMM
                if X pressed jump to End
                if J pressed jump to ConnectToNetwork
                if I pressed jump to Instructions
Instructions:
        GameInstructions
                Jump to MainMenu

ConnectToNetwork:
        ClientPacketSend
                Wait for server packet to start game
        StartMIDI
 

GameLoop:
            ClientPacketRecieve
                    poll for packet
                    This will contain the opposing player's structure.
            CheckESCPressed
                    if so jump to EndSequence
            LifeCheck
                    if Thack is dead jump to EndSequence
            InitBuf
            DrawGameScreen
                      uses DrawGSObject, DrawGSUnits, DrawOwnership
           DrawControlBar
                      uses DrawMinimap, DrawSelectedUnit, DrawSUHealth,
                             DrawSUName, DrawHealthTick, DrawMiniBlock,
                             DrawCavemanBuild.
           DrawScreen
           ScrollScreen
                check if screen needs to be scrolled, if so change ViewPort X and Y
           MouseCheck
                Use mouse interrupt to obtain mouse position and click status.
            MouseCalculate
                Determine exact grid clicked, determine if unit selected or moved.
                Play sounds as needed.
            BuildCaveMan
                Check if new caveman being made (hut selected, b pressed)
            BuildNewWall
                        Will Call BuildWall if a new wall needs to be built
            MoveUnit
                        uses CheckGridPos, CheckGridFit, MoveUnitHelper
            Check for Attack situations and damage
                        uses CheckMyPain, CheckCaveman0
            ClientPacketSend
                        jump to GameLoop
EndSequence:
            StopMIDI
            GameOverSequence
                    jump to End

End:
        DeInstKey

GameMain endp


Questions?
E-mail Matt Wood (mdwood@uiuc.edu)
or any other team member
Tim Zadigian : Sound/Gameplay
Dan Mueller : Input/Gameplay
Mike Del Giudice : Networking/Gameplay