Scripting Examples

Speed

  • About: As part of my efforts to improve my proficiency with Lua, I spent part of my 2012 winter break making mobile games in Lua (with the assistance of the Corona SDK).  For one of these games, I created a fully functional multiplayer version of the card game Speed.
  • Tech: Lua & Corona SDK
  • Dev Time: 10 hours
  • Code Sample:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
-----------------------------------------------------------------------------------------
--
--Create card deck and assign out the face value, suit, and image of each card
--
-----------------------------------------------------------------------------------------
    for i=1, deckSize do
        if i<=13 then
            cardDeck[i] = {i, "Hearts"}
        elseif i<=26 then
            cardDeck[i] = {i-13, "Diamonds"}
        elseif i<=39 then
            cardDeck[i] = {i-26, "Spades"}
        elseif i<=52 then
            cardDeck[i] = {i-39, "Clubs"}
        end

        --Assigns images based on card value and suit
        cardDeck[i][3] = display.newImage( "images/Cards/" .. cardDeck[i][1] .. cardDeck[i][2] .. ".png", 0, 0 )
    end

-----------------------------------------------------------------------------------------
--
-- Player Cards
--
-------------------------------------------------------------------------------------------

--Array for both players; active card hands
    for i=1, playerCardNumberTotal do
        playerCards[i] = getRandomCard()

        if (i <=playerCardNumber) then
            playerCards[i][3].y = display.contentHeight - cardHeight/2
            playerCards[i][3].x = offset1
            offset1 = offset1+100
        else
            playerCards[i][3].y = 0 + cardHeight/2
            playerCards[i][3].x = offset2
            playerCards[i][3]:rotate(180)
            offset2 = offset2+100
        end
    end
   

    --Create player 1 card buttons
    for i=1, playerCardNumberTotal do
        if ( i<= playerCardNumber) then
            playerCardButtons[i] = display.newRect(playerCards[i][3].x, playerCards[i][3].y, cardWidth, cardHeight)
            playerCardButtons[i].x = playerCards[i][3].x
            playerCardButtons[i].y = playerCards[i][3].y
            playerCardButtons[i]:setFillColor (5, 50, 200, 150)
            playerCardButtons[i]:toBack()
        else
            playerCardButtons[i] = display.newRect(playerCards[i][3].x, playerCards[i][3].y, cardWidth, cardHeight)
            playerCardButtons[i].x = playerCards[i][3].x
            playerCardButtons[i].y = playerCards[i][3].y
            playerCardButtons[i]:setFillColor (5, 50, 200, 150)
            playerCardButtons[i]:toBack()
        end
    end
end

-----------------------------------------------------------------------------------------
--
-- Random Card Function
--
-----------------------------------------------------------------------------------------

--Picks a random card from the cards remaining and then removes it from the deck
function getRandomCard()

    if (randomCardsRemaining > 0) then
        --Gets the index number of the card so we can refer to it later
        randomCardIndex = math.random(1, randomCardsRemaining)
        --Sets card to the actual card info in cardDeck
        card = cardDeck[randomCardIndex]
        table.remove(cardDeck,randomCardIndex)
        randomCardsRemaining = randomCardsRemaining - 1
    else
        discardCardIndex = math.random(1, discardCardsRemaining)
        card = cardDiscard[discardCardIndex]
        table.remove(cardDiscard,discardCardIndex)
        discardCardsRemaining = #cardDiscard
    end

    print (card[1], card[2])

    return card
end

Download Project

Breakout

  • About: My first foray into Lua was creating the classic arcade game Breakout as part of a class at the Guildhall.  The professor created the basic building blocks of the program (loading libraries, drawing functions, etc.), and I created the rest of the game (paddle/ball/block functionality, scoring system, music and sounds, etc.).  I also expanded on the existing functionality of the program to create additional features like two separately controlled paddles and random level generation.
  • Tech: Lua
  • Dev Time: 30 hours
  • Code Sample:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
--[[-------------------------------------------------------------------
Paddle collisions
--]]
---------------------------------------------------------------------Local variables for ease of reference and logic below
local leftBallX = self.newPosition.x
local rightBallX = self.newPosition.x + self.material.w
local topBallY = self.newPosition.y
local bottomBallY = self.newPosition.y + self.material.h
local currentTopBallY = self.position.y
local currentBottomBallY = self.position.y - self.material.hlocal paddle = gameState.actors[gamePlayer.actorIndex]
local leftPaddleX = paddle.newPosition.x
local rightPaddleX = paddle.newPosition.x + paddle.material.w
local topPaddleY = paddle.newPosition.y
local bottomPaddleY = paddle.newPosition.y + paddle.material.w
local leftPaddle2X = paddle.newPosition2.x
local rightPaddle2X = paddle.newPosition2.x + paddle.material2.w
local topPaddle2Y = paddle.newPosition2.y
local bottomPaddle2Y = paddle.newPosition2.y + paddle.material2.hlocal paddleMiddle = (leftPaddleX + rightPaddleX) / 2
local paddleMiddle2 = (leftPaddle2X + rightPaddle2X) / 2
local ballMiddle = (leftBallX + rightBallX) / 2
local english = (ballMiddle - paddleMiddle)
local english2 = (ballMiddle - paddleMiddle2)--Checks if ball is within X coordinates of paddle
if (rightBallX &gt;= leftPaddleX) and (leftBallX --Checks if ball is within Y coordinates of paddle, and the third comparison makes sure the ball was above the paddle
if (bottomBallY &gt;= topPaddleY) and (bottomBallY self.velocity.y = 0 - self.velocity.y--Adjusts velocity based on English
if (self.velocity.x &lt; 0 ) then
self.velocity.x = 0 - english
end
if (self.velocity.x &gt;= 0) then
self.velocity.x = english
end--Checks if ball's new positive velocity is higher than max speed
if (self.velocity.x &gt; self.maxSpeedX) then
self.velocity.x = self.maxSpeedX
--Checks if ball's new negative velocity is lower than inverse of max speed
elseif (self.velocity.x &lt; 0 - self.maxSpeedX) then
self.velocity.x = 0 - self.maxSpeedX
endMix_PlayChannel(-1, gameSounds.assets[2], 0)
end
end--Checks left and right collision for second paddle
if (rightBallX &gt;= leftPaddle2X) and (leftBallX--Checks if paddle is being hit from the top
if (bottomBallY &gt;= topPaddle2Y) and (bottomBallY self.velocity.y = 0 - self.velocity.y--Adjusts velocity based on English
if (self.velocity.x &lt; 0 ) then
self.velocity.x = 0 - english2
end
if (self.velocity.x &gt;= 0) then
self.velocity.x = english2
end--Checks if ball's new positive velocity is higher than max speed
if (self.velocity.x &gt; self.maxSpeedX) then
self.velocity.x = self.maxSpeedX
--Checks if ball's new negative velocity is lower than inverse of max speed
elseif (self.velocity.x &lt; 0 - self.maxSpeedX) then
self.velocity.x = 0 - self.maxSpeedX
endMix_PlayChannel(-1, gameSounds.assets[2], 0)
end--Checks if paddle is being hit from the bottom
if (bottomBallY &gt;= topPaddle2Y) and (bottomBallY = bottomPaddle2Y) then
--Reverses velocity
self.velocity.y = 0 - self.velocity.y--Adjusts velocity based on English
if (self.velocity.x &lt; 0 ) then
self.velocity.x = 0 - english2
end
if (self.velocity.x &gt;= 0) then
self.velocity.x = english2
end--Checks if ball's new positive velocity is higher than max speed
if (self.velocity.x &gt; self.maxSpeedX) then
self.velocity.x = self.maxSpeedX
--Checks if ball's new negative velocity is lower than inverse of max speed
elseif (self.velocity.x &lt; 0 - self.maxSpeedX) then
self.velocity.x = 0 - self.maxSpeedX
endMix_PlayChannel(-1, gameSounds.assets[2], 0)
end
end--Set new position of ball
self.newPosition.x = self.newPosition.x + self.velocity.x
self.newPosition.y = self.newPosition.y + self.velocity.y
self.position = self.newPosition

GuildEd Extensions

  • About: Because I did well on the Breakout assignment, my professor gave me the option of doing additional work in Lua to expand the functionality of GuildEd, the Guildhall’s proprietary 2D engine.  I expanded the basic functionality of actors by creating new actions like double jumps, flying, and teleporting (including support for custom animations and sounds, editor-based modifications to the functions, etc.)
  • Tech: Lua & GuildEd
  • Dev Time: 15 hours
  • Code Sample: N/A because the engine has not been released to the public

Clue N (Text Adventure)

  • About: One of the first programs I ever coded was a classic murder mystery text adventure I wrote in C#.  The player travels through a house with six rooms, interacts with nearly 30 different objects, improves character-specific stats to gain access to new options, and converses with several NPCs throughout the course of the adventure.
  • Tech: C#
  • Dev Time: 35 hours
  • Code Sample:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
while (!bDone)
{
//Refers to getRoom function to take user input and change the current room
currentRoom = getRoom(house, currentRoom);//This is a safety precaution just in case the user somehow is able to enter a value less than 0 (this should never happen)
if (currentRoom &lt; 0)
{
Console.Write("\n\nThere is no door there! Press any key to continue.");
Console.ReadKey();
Console.Write("\r ");
Console.SetCursorPosition(0, Console.CursorTop - 2);
Console.Write("\r ");
Console.SetCursorPosition(0, Console.CursorTop);
}//Contains all information for room 0
else if (currentRoom == 0)
{
Console.Clear();
Console.ForegroundColor = ConsoleColor.Magenta;
Console.WriteLine(house[currentRoom].name);
Console.WriteLine(house[currentRoom].descr);//Set to false so the player can access this section if he comes back to it
bMove = false;//While the character is not moving to another room
while (!bMove)
{
Console.WriteLine("Would you like to interact with this room (I) or move to a different room (M)?");
cki = Console.ReadKey();
cInteraction = cki.KeyChar;//If the character says they want to interact with the room
if ((cInteraction == 'i') || (cInteraction == 'I'))
{
//This deletes previous input to maintain cleanliness of the console
Console.Clear();
Console.WriteLine(house[currentRoom].name);
Console.WriteLine(house[currentRoom].descr);
Console.WriteLine("Available Actions:\n");
Console.WriteLine("Move the dresser (M)");
Console.WriteLine("Look in the mirror (L)");
Console.WriteLine("Take a nap on the bed (N)");
Console.WriteLine("Stop interacting with the room (S)");//Set to false so the player can access this section if he comes back to it
bDoneInteracting = false;//While the character is not done interacting
while (!bDoneInteracting)
{
cki = Console.ReadKey();
cInteraction = cki.KeyChar;//If the player selects this action
if ((cInteraction == 'm') || (cInteraction == 'M'))
{//Player cannot move the dresser if his strength is less than 10
if (you.strength &lt; 10)
{
//These all delete the player character input for console cleanliness
Console.Write("\r ");
Console.SetCursorPosition(0, Console.CursorTop);
Console.WriteLine("\nYou are too weak to move the dresser. If only you could get stronger somehow.");
}//If the player strength is high enough
else
{//If you have not received the key already
if (you.haveKey == true)
{
if (!you.haveClueN)
{
Console.Write("\r ");
Console.SetCursorPosition(0, Console.CursorTop);
Console.WriteLine("\nYou find a small locked box behind the dresser.");
Console.WriteLine("You use the key to open the box and find pictures of Ms. Turkey killing the butler.\nThey seem to be screen captures from Major Mayonnaise's Kinect. This must be Clue N.");
you.confidence = 20;
you.haveClueN = true;
}
else
{
Console.Write("\r ");
Console.SetCursorPosition(0, Console.CursorTop);
Console.WriteLine("\nYou already have Clue N. Time to put it to good use.");
}
}else
{
Console.Write("\r ");
Console.SetCursorPosition(0, Console.CursorTop);
Console.WriteLine("\nYou find a small locked box behind the dresser.");
Console.WriteLine("It looks like it could be opened, but you don't have the key.");
}
}
}//If the player selects this action
else if ((cInteraction == 'l') || (cInteraction == 'L'))
{
Console.Write("\r ");
Console.SetCursorPosition(0, Console.CursorTop);
Console.WriteLine("\nYou look in the mirror and see a beautiful person ... on the inside.");
}//If the player selects this action
else if ((cInteraction == 'n') || (cInteraction == 'N'))
{
Console.Write("\r ");
Console.SetCursorPosition(0, Console.CursorTop);
Console.WriteLine("\nYou take a nap in someone else's bed. Strange.");
}//If the player wants to stop interacting with the room this exits the while room
else if ((cInteraction == 's') || (cInteraction == 'S'))
{
Console.Clear();
Console.WriteLine(house[currentRoom].name);
Console.WriteLine(house[currentRoom].descr);
bDoneInteracting = true;
}//If the player enters an invalid action
else
{
Console.Write("\r ");
Console.SetCursorPosition(0, Console.CursorTop);
Console.WriteLine("\nPlease enter a valid action.");
}//If the player interacts once but is not done interacting, the program waits for input and then resets the room text
if (!bDoneInteracting)
{
Console.ReadKey();
Console.Clear();
Console.WriteLine(house[currentRoom].name);
Console.WriteLine(house[currentRoom].descr);
Console.WriteLine("Available Actions:\n");
Console.WriteLine("Move the dresser (M)");
Console.WriteLine("Look in the mirror (L)");
Console.WriteLine("Take a nap on the bed (N)");
Console.WriteLine("Stop interacting with the room (S)");
}
}
}//If the player chooses to move to a different room instead of interacting with this room
else if ((cInteraction == 'm') || (cInteraction == 'M'))
{
//Erases the section asking the player to choose between move and interact
Console.Clear();
Console.WriteLine(house[currentRoom].name);
Console.WriteLine(house[currentRoom].descr);
Console.WriteLine("Available Actions:\n");
Console.WriteLine("Go North to " + house[house[currentRoom].goN].name + " (N)");
bMove = true;
}//If the player wants to quit, this exits the program
else if ((cInteraction == 'q') || (cInteraction == 'Q'))
{
bDoneInteracting = true;
bMove = true;
currentRoom = 9;
}else
{
Console.Write("\r ");
Console.SetCursorPosition(0, Console.CursorTop);
Console.WriteLine("\nThat is not a valid input.");
Console.ReadKey();
Console.Clear();
Console.WriteLine(house[currentRoom].name);
Console.WriteLine(house[currentRoom].descr);
}
}
}
}

 

Last Light Turrets

  • About: As part of a level I made for Gears of War, I created a custom turret sequence that allows players to fire three remote-controlled turrets simultaneously while fending off waves of Locust.
  • Tech: Kismet & Gears of War Editor
  • Dev Time: 15 hours
  • Kismet Sample: 

Voodudes Thesis

  • About: My thesis project seeks to measure the development cost and attendant benefits of ancillary gameplay elements like mini games, meta games, interactive toys, and combat arenas.  I created one of each to expand Voodudes and test my thesis.
  • Tech: Kismet & Voodudes UDK
  • Dev Time: In progress
  • Kismet Sample: Because this is a work in progress, there are no samples available yet.  I will update this section in March when I near the completion of my thesis.

Voodudes Baron Chicken Cinematics

  • About: In addition to making all of the story cinematics for the game, I created two machinima for the final boss fight.  The first one introduces the giant skeletal chicken and its attack, and the second one shows the destruction of the final boss.
  • Tech: Kismet/Matinee & Voodudes UDK
  • Dev Time: 7 hours
  • Matinee Sample: 
vooscripting8

Adding funny chicken screams and slow-motion effects made the introduction of the giant skeletal chicken a memorable moment in the final boss.

vooscripting10

By controlling the subtle up and down movements and animations of the chicken in a separate matinee, I was able to control the large movements through the play space in the main matinee.

Headcrab Highscore

  • About: One of my most interesting scripting challenges came through scripting in Hammer for Half-life 2.  The mod I made for the game had players using the gravity gun to grab and launch an endless stream of headcrabs into various laser-covered targets.  The real challenge for this was creating a scoring system in a node-based scripting engine that had no support for storing, accessing, or displaying variables.  To accomplish this, I took the following steps:
    1. Created three counter entities and allocated each one as a digit in a three-digit score
    2. Incremented the first counter (the ones place) until it reached 10, upon which I would set it back to 0 and increment the second counter (the tens place) to 1
    3. Placed 30 text entities (10 for each digit in the score), arranged them to be adjacent to one another on the player’s HUD, and toggled the display of the entities to match the current value in each counter
    4. Attached timers to each text entity to update them frequently and check to see if they should be on or off
  • Tech: Hammer
  • Dev Time: 8 hours (scoring system only)
  • Scripting Sample:

Resume/Contact