|
Project 4: A Game
Option #2: Arcade
starter code for the arcade option
In this project you will be making your own 80s-style video arcade game. In these games, a player sits in a small two-dimensional world, sometimes inhabiting a ship or a vehicle that allows them to move around in the world. They have some task to accomplish and survive challenges that the world presents. The game is graphics-based: it presents a view of the whole world, or some portion of it, and the player has to react to objects that come after them, or has to go after things that surround them. The player reacts or moves “in real time”—they have to react guickly or they will lose the game.
For example, Asteroids is a video game where a player sits in a craft in the middle of deep space. Deep space has asteroids that pass near the spacecraft and the player has to avoid being hit by them in order to survive. Luckily the craft is outfitted with thrusters, allowing it to change heading and accelerate, move it through space. It is also armed with photons it can use to obliterate the asteroids within range. The player earns points by destroying these asteroids.
As another example, Pong is a two-player game that is a kind of digital indoor tennis. Two players appear as vertical “paddles”, on each side of a horizontal court, and they each serve and strike a bouncing ball in the direction of their opponent, themselves trying not to miss the ball when it approaches their paddle.
I’ve provided Python code that implements these two video games. You can run them by running either PlayAsteroids.py or PlayPong.py and following their instructions. They each open a graphical display and animate their gameplay. You can play each by hitting keys on the keyboard. Pong is a two-player game, so you can find a friend and share a keyboard with them to volley. Pong also can be put into a mode where you use the mouse to control the paddle. (On the Mac, using the mouse, you’ll want to maximize the window, as strange things happen when the window loses “focus” with the cursor wandering outside the window’s bounds.)
The code relies on Python’s Tcl/Tk interactive library tkinter . This library allows us to bring up a window Frame with an embedded Canvas on which we draw the world—either deep space or the court— and its objects. Each game extends a Game class, described in Game.py , which has methods for displaying the game’s world and updating the state of the objects in the world. In this way, the code is very similar to a simulation, much like the program you developed in Project 3. Here, objects appear within a two-dimensional world, and so typically have a location specified by an x-y position. Each game agent a that appears has an a.shape() and an a.color() method that allows the game to draw them, along with an a.update() method that changes their state with each step of the simulation. There’s a update made for each frame of the animation of the action of the game.
The game code listens and reacts to the user’s keypresses and mouse movements. This reacting is performed by methods, called event handlers, and their code gets called by the Python/Tk system so that you can perform game actions on behalf of the user playing the game.
The game updates synchronously using its update
method. Each call to update leads to a regular lock-step
modification of the states of all the agents and the world, followed by
their rendering on the screen. These updates and renderings occur
at the rate that the game animates its graphics, frame-by-frame at a
certain frame rate.
The player controls the game with mouse movememts and keyboard keypresses.
These events happen asynchronously and there are methods that
handle these events. You'll want to write this event-handling code so
that these actions are registered within the attributes of the game’s world
or within the game’s agents. When the game world and its agents are updated,
they can move or react according to the user input actions that occurred in
between that frame and the prior frame. For example, in pong, if the
the left player's up direction key is types, then we set the direction
of movement of that player's paddle. At the next update of the paddle,
the paddle moves upward one step.
You should take a look at the code to get a feel for how these games work. You’ll see that each has a main class PlayAsteroids or PlayPong that are subclasses of Game . Their __init__ sets up the game state and populates the world with its objects. Each game object’s update method drives the simulation by updating the state of the game, which includes calling their superclass Game’s update method. This code updates each game agent’s state and then draws each game agent in the window. The agents are organized as subclasses of an Agent class, also defined in Game.py . The asteroids game has various Asteroid subclasses, a Ship class, and a Photon class. The pong game has a Paddle class and a Ball class.
Once you get comfortable with the code, you should start writing the code of your own game. This can involve you writing your own Game and Agent subclasses from scratch, and slowly adding features to flesh out the action of that game. Alternatively, you can work instead with the asteroids and pong games, and enhance them by adding more and more features to their gameplay. You get points for each of the features you add, and you get a baseline set of points if you build a game from scratch instead of extending asteroids/pong. We list a collection of enhancements below, suggesting features that make them like classic arcade games.
I have included an examples folder with compiled Python code for a few different games written by students in the past. Note that I’ve chose ones that mimic some standard 80s arcade games, but you are not limited to only those of course. To run them, use the .pyc file for your version of Python. I’m running version 3.10 so I would type
python3 gravity-310.pyc
to run the gravity game. There’s also invaders , hit_space , and pede to try.
As you add features to your game, make sure you are fulfilling the assignment, earning enough points by implementing these features. You must earn at least 20 points to get a passing grade on the assignment, though you should aim to earn at least 40. You can pick which improvements to make, but remember that your goal isn’t just to check off boxes by making the improvements. Instead, work to make something that is a good game.
The improvements are not explained in the sort of specific detail that would tell you exactly what changes they include. You have to add this functionality in a way that you think makes the game good, fits the logic of the game. If you are adding prizes that appear that the player can collect, how should they get introduced to the world in a way that makes sense? If you are adding antagonists that attack the player, how should they appear and what should they do? And how does the player combat them?
You should plan your improvements so that they can be made incrementally. Don’t expect to be successful if you try to write all the code at once. Make small changes and test each of one. If a small change works, then make another change. If not, see if you can make a simpler change, get that working, and then use that experience to make the change more complex. This is the fun and the craft of engineering this kind of code. Planning out enhancements and features is an art that is best learned with experience, and you’ll find that early enhancements better help you understand how best to make later ones.
Because the code is object-oriented, you might find it tricky to determine which part of the code should do what, or which part of the existing code does what. Determining the layout of code and the responsibilities of classes and methods is an art, too. You’ll find that, as you go, there are good places to add features and good ways to structure everything. There can be bad ways too. It’s not unusual to have to restructure or rewrite code in order to add features, rather than making the code bend and stretch awkwardly for each addition.
You must create a document that briefly describes your game and explains its gameplay. That document should list all the improvements you’ve made, the points you feel you earned for each, and a brief explanation of what specifically you did for each improvement. Sometimes there will be very little to say, but if the improvement gave you freedom to choose how things work, you should say what you chose to do. If you add an antagonist or an obstacle, for example, say what you added and what is special about it. You should also have a quick note about where the code was added/modified to make this work. You are also free to make improvements that aren’t on the list of options, just descrive what they are. The document you develop should explicitly enumerate and tally for us the points you feel you have earned with your work.
Your project will be evaluated in several ways. These are:
How many points did you earn from your improvements?
How well did you make the improvements you made? Did you do the minimum to make it count, or do something very challenging? Were there bugs? Were the improvements made in a way that was easy for the user to understand? Were they incorporated well into the game?
How good is the overall game? You should be trying to make a game that is actually fun to play. Pick improvements that help you achieve this and try to design the game well. Make your improvements well-integrated into the game. You should give initial instructions that describe the basic gameplay, but include interludes as new objects (antagonists, prizes, obstacles) get introduced so that the player will know how to deal with them.
Did you make regular progress in your coding? We will have several “milestones” for this project that we’d like you to reach, and you should think of their dates as real deadlines to meet before the final submission deadline. For these intermediate deadlines you will report by demonstrating your game to us, and show us how much of the work you have completed at each stage. You will be evaluated on your progress with each of these minor deadlines, in addition to what you’ve completed by the major deadline. Start early, do not let this assignment sit.
How well documented is your code and how understandable is it? This applies both to comments in the code and to the document you’re submitting. Your code should be well-written and readable, and we should be able to figure out what you did and how you did it.
Some notes on the work:
Other than the supporting Game.py and geometry.py , the example games have the whole game’s code in a single file. It is also normal to write the code so that each class, or collections of similar classes, each lives in its own Python file. If your game gets complicated, you might want to structure it this way. If so, tell us how the code is organized. Regardless, it’d be good to give us a summary of all the classes you built.
On the one hand, you should think ahead and have an idea of what you want your game to end up looking like before you start writing code. On the other hand, you might just start prototyping things, working from our code, to see what’s possible. If you get some early version working, but then decide to rework the game to be something different, feel free to include your initial “experimental” games in subfolders with your hand-in. Regardless, make sure the code is working nearly all the time, adding working features (obstacles, etc.) one at a time, getting each enhancement working, before moving onto the next. Work simply first then make things richer later. I can’t stress this enough: don’t just write all the code and hope that it works.
Leave time for general testing of the game at the end. Even once all of the technical improvements have been made, you will want to change things around a bit to make the game better. Have a friend play the game and see if they enjoy it, if they can figure out how to play, etc. We formalize this process with the “beta test” deadline in the last week.
The starter code is meant to be starter code. It is okay to change things. You should also not assume everything is done perfectly. It can be treated as a suggestion of what’s possible, but you can research and use other libraries to make your game.
Working with Partners
You are allowed (even encouraged!) to work with a partner on this project. If you do so, you must both contribute roughly equal work to the project. I expect a slightly more ambitious game from you. You will need 25 points to pass and should aim for at least 50 total points (as opposed to 20 and 40 for single individuals).
You should also submit a brief description of who did what work. (This should be no more than a page, probably substantially shorter.) Did you sit at a computer together working? Split things up? Test each others’ code? You should describe briefly what parts each person worked on, what was worked on together (and what “worked on together” meant for you) and how you coordinated your efforts.
This is a small enough project that coordinating the efforts of two people should not be too complicated, but if you’re interested, I would recommend using a Git repository. (These can be set up for free online, and a quick google search will give not only the needed resources but also instructions on how to use git.) Let me know if you need help with this.
Deadlines
This project will include several intermediate deadlines.
Game Proposal: Friday, November 18th. Submit a brief text file to the homework submission system. This should say who you will partner with (if anyone) and the general game idea. (The game idea is just a very basic description-– two or three sentences should be plenty.) If you are working with a partner, you should both separately submit the same file.
Progress check-in: Tuesday, November 29th. By this day you should have done the work to have earned at least 20 points, 30 ideally, though perhaps crudely implemented. Briefly show these changes to a TA or professor during lab or during TA evening hours. We will evaluate your progress.
Project submission: Tuesday, December 13th. Submit your game’s code and any of its supporting files, a description of your game and instructions for playing it, and a report of the features you implemented with a breakdown of the point total you reached.
Menu of changes and additions
basic platform (12 points): have a player object that can move around in some way. Have a class of obstacles or a class of antagonists that appear in the game initially or that are introduced during the game’s play. The player should either avoid or interact with these in some way. For the asteroids game, we have the ship and we have different types of asteroids that get introduced. The asteroids can be shot by the ship, and the ship moves around.
game pause/resume (4 points) introduce a way that the gameplay can be paused and then resumed. This could be a keystroke or, more elaborately, a “safety” object or room that the player hits/touches/enters. This should be done cleanly and integrated with the game object’s update method in a good way.
status (2 or 4 points): Display an update of the status of the game. This could include things like the score, the number of lives, etc. Perhaps this can be shown when the game pauses, or can be printed in the terminal or console (see the pong game to see how it’s done there). If this display is graphical, then it’s worth 4 points. If it’s just text or console output, then it’s worth only 2 points.
prelude (4-6 points): Have a moment before the game starts, perhaps even animated. It could give a menu of options for game play, a story about the game, or allow the user to ask for instructions. For pong that would have been a menu of a pong-like games (tennis, racquetball, a doubles match; see the “game variants” option below). For asteroids that would have been a configuration of the game’s features (number of asteroids, ship speed, limited number of photons).
win/lose and scoring (4 points): Make it so that the player can lose (or die) in some way. Make it so the player can win in some way. For asteroids, the player should lose a ship when hit by an asteroid; they could move to a new level or screen of asteroids when they clear the current one. They should gain or lose points with a win or loss, and/or gain and lose lives with a win or loss. The key to making this change is adding the accounting scheme for the player’s score and tracking when the win/loss occurs, and maybe starting again when the loss (of life) happens.
shields (3 points): Add a feature where a player can deploy a shield, one that protects them from hitting obstacles (or being hit by them) or from being attacked by antagonists. The shield should have a limited lifetime. Also, there should be a limited number of uses available.
megabomb (3 points): Add a feature where a player can deploy a device that has a severe effect on several (or all) the things on the screen they are combatting. For asteroids, maybe that could be all the small asteroids getting destroyed.
transporter or wormhole (3 points): Allow players to either spontaneously be placed elsewhere on the screen or escape to another screen. This could either be deployed in a manner similar to a shield (a transporter option), or when bumped into on the screen (a wormhole). In the latter case, you could have pairs of wormholes to enrich the topology of the game beyond just the 2-D plane.
a second, new kind of antagonist (5 points): Introduce a second type of antagonist that goes after and can cause damage to the player, ones that can be defeated in some way by the player. Asteroids traditionally had two sizes of alien ship that would appear now and then, and one of these would randomly shoot in random directions.
bigger world (4 points): The asteroids game starts in a single bounded universe (with the wraparound “space war” topology that makes it like the surface of a torus/donut). Make the game wider than a single screen. For example, you could have the game scroll left/right when the player moves to the ends of the screen. Alternatively, if the player moves off the edge of the screen, perhaps that should put them onto a different screen, or in a different world. You could also have this happen with a wormhole.
limited power (4 points): Limit the players ability in some interesting way, now and then. Perhaps they can only perform certain actions in certain situations, or if they’ve gained certain things. For asteroids, maybe they have only so many photons that can be shooting at once.
prizes (2-4 points): Have objects appear that the player can pick up or run/fly through. The prize can simply earn them a higher score (an enhancement worth 2 points) or it could help them in their game play (an enhancement worth 4 points). If earning a prize gives them one of the other features (say, a shield or a transporter or an extra life) then this enhancement is worth only 2 points for each. Make it so the player wants to collect these prizes.
damaged mode (3 points): Have a situation arise that creates problems for the player, reducing their effectiveness in some way. Or maybe it’s a “bad prize” in disguise, and one that effects their play. Either the damage mode expires or make it so that some action heals them.
pickup/dropoff (3 points): Have items that can be picked up and dropped off. Make it so that the player’s goal is to transport these items from one place to another.
containers/repositories (3 points): Have places in the world where a player can grab things and/or deposit things. For asteroids, as an example, you could introduce “mining” asteroids that don’t explode. Rather the ship changes their state by shooting them, and they release prizes prizes when shot enough. Basically, I want you to make objects that have a richer state and that the player can interact with.
levelling up (4 points): Make all the obstacles and antagonists get harder as gameplay continues and as the player is succeeding in surviving. Make collection of certain prizes necessary for them to survive in the trickier circumstances, and introduce these prizes as game play continues. For asteroids, maybe more get put on the screen, alien spaceships appear more frequently and/or their shots become more accurate, the asteroids move faster, etc.
alternate physics (5 points): Every now and then, or due to some action, have the game switch modes so that the interactions change considerably. For pong this could be a phase where the ball falls to the bottom due to gravity, and so bounces in arcs. For asteroids it could be the introduction of a “magnetoid” that pulls the ship in its direction, or a “black hole” that appears in the center of the screen and affects the movement of both the ship and the asteroids on the screen. Or, in a game, with lots of antagonists, it just changes their behavior considerably (they run away or move more erratically).
loot (2 points): Make it so that defeating an antagonist causes useful prizes to appear. There should be some amount of randomness about what those items are, or whether those prizes appear at all.
interludes (2-4 points): After a player completes a level or accomplishes some goal, play an animation (4 points) or tell a story about what will happen next (2 points). Or, make it so that some prize or interaction brings up a menu or leads to an interlude (2 points)
game over/you win (4 points): Make a spectacular animated sequence that tells them when the game has ended. This could tell them what kind of doom the world faced due to their players failure and series of mistakes. Or hints about the new world that their success enabled. Or it could just be something pretty and cool to make them want to play the game again (and not feel too bad that they lost).
games within the game (8 points for the 2nd, 6th for the third, etc.): When a player reaches a certain level or accomplishes a certain goal, have them play a different game, one that fits with the theme of the main game, but has quite different goals and gameplay. You can enhance this game to earn points here, instead of in the main game. But you can only count one per option (e.g. if both games have a shield, you only earn 2 points total for building the shield feature). You can also instead craft a collection of games in an arcade. They need to be different enough to earn each.
breakout rules (6 points): Introduce obstacles in the scene (doors, walls, etc.) that can be shot or touched to essentially change the layout or connectedness of the world. A classic example of this would be the game Breakout, where a pong-like paddle could wear bricks off a wall with each bounce of the ball it volleys. Another is in the game Dig Dug, where players could dig tunnels through their world. You may need to add Scene objects, not just Agent objects, that have different drawing methods than shape() or color and so are treated and drawn differently by the Game .
multiplayer (4 points): Make it so that two or more players can play the game on the same run, and are competing against each other’s score. This could have them alternate turns, say. When the one player loses/crashes/dies/is shot, ending their turn, then the other player plays a turn.
artificial intelligence (? points, no more than 8): Have the antagonists be very clever in their activity, or have an automated player that plays the game, one who you are trying to outplay. Depending on their sophistication, this could earn you up to 8 points. For pong it seems pretty easy and is worth a few points. For asteroids, this could be random and easy, or quite sophisticated.
choose your own (? points): Make whatever changes you want, beyond the required points, if it helps make the game better. If it’s important to you to get points for these changes, talk to Jim or Meaw to figure out how many points they are worth.
|
|