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 |
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 >= 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 >= topPaddleY) and (bottomBallY self.velocity.y = 0 - self.velocity.y--Adjusts velocity based on English if (self.velocity.x < 0 ) then self.velocity.x = 0 - english end if (self.velocity.x >= 0) then self.velocity.x = english end--Checks if ball's new positive velocity is higher than max speed if (self.velocity.x > 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 < 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 >= leftPaddle2X) and (leftBallX--Checks if paddle is being hit from the top if (bottomBallY >= topPaddle2Y) and (bottomBallY self.velocity.y = 0 - self.velocity.y--Adjusts velocity based on English if (self.velocity.x < 0 ) then self.velocity.x = 0 - english2 end if (self.velocity.x >= 0) then self.velocity.x = english2 end--Checks if ball's new positive velocity is higher than max speed if (self.velocity.x > 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 < 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 >= topPaddle2Y) and (bottomBallY = bottomPaddle2Y) then --Reverses velocity self.velocity.y = 0 - self.velocity.y--Adjusts velocity based on English if (self.velocity.x < 0 ) then self.velocity.x = 0 - english2 end if (self.velocity.x >= 0) then self.velocity.x = english2 end--Checks if ball's new positive velocity is higher than max speed if (self.velocity.x > 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 < 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 < 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 < 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:
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:
- Created three counter entities and allocated each one as a digit in a three-digit score
- 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
- 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
- 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: