diff --git a/README.md b/README.md index 85fefeb..12e762a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,138 @@ -# InteractiveProgramming +# "Pain Train" the Video Game +### by Charlie Weiss and Diego Garcia -This is the base repo for the interactive programming project for Software Design, Fall 2016 at Olin College. +## What is this? +This is a video game created using Python's pygame library and an MVP (model-viewer-player) framework. It is a platform game with a player, a chaser, and some obstacles. The player loses by either being overtaken by the chaser, or by falling to their death. +## How does it work? +The code is split into three collections of classes: The Model classes, the View classes, and the Controller classes. The functions in these classes are called by the main function (found at the bottom of the file), which runs the game with a while loop. Here's some more detail about those sections: -To run the game, run the file main.py in your terminal. +### Model Classes +These contain the definition of the models of each type of object in the game, and their interactions with other objects or events. Each class defines things such as an object's postion, height, width, and distance traveled per loop. Here's an example of the chaser model class, named PainTrain: + +``` +class PainTrain(object): + def __init__(self,x=0,y=0,width=200,height=200,constdx=.05,dx=0,shiftdx=-1): + # places train centered above coordinate given + self.x = x + self.y = y-height + self.width = width + self.height = height + self.constdx = constdx + self.dx = dx + self.shiftdx = shiftdx + + def step(self): + self.x += self.constdx +``` + +The classes you will find here are +- Player +- PainTrain +- Ground +- Platform + +### Viewer Classes +These classes project the information contained in the model classes onto your screen. Each contains an initial function to define the class, and a draw function that says what the object should look like. For consistency's sake, here's the example of the PainTrain's Viewer class: + +``` +class PainTrainView(object): + def __init__(self, model): + self.model = model + + def draw(self, surface): + model = self.model + # this takes (x,y,width,height) + pygame.draw.rect(surface,BLACK,(model.x,model.y,model.width,model.height)) +``` + +The classes you will find here are +- PlayerView +- PainTrainView +- GroundView +- ObstacleView + +### Controller Classes +This is actually one class called the Controller class. It has an initial function to define it, and a handle_event function. This class interacts with the main function, which passes it an event. The handle_event function then determines which event it is (i.e., which key has been pressed), and says what to do in that case. Here's the class: + +``` +class Controller(object): + def __init__(self,models): + self.models = models + self.player = models[0] # make sure this aligns with controlled_models in main + + def handle_event(self): + # time passed isn't actually time based... based on while loop efficiency + player = self.player + models = self.models + keys = pygame.key.get_pressed() # checking pressed keys + for model in models: + if keys[pygame.K_LEFT]: + if player.go_back(): + model.x -= model.shiftdx + else: + model.x -= model.dx + if keys[pygame.K_RIGHT]: + if player.shift_world(): + model.x += model.shiftdx + else: + model.x += model.dx + + if keys[pygame.K_UP] and player.dy == 0: + player.dy = player.jumpdy +``` + +The class you will find here is +- Controller + +### Main Function +Now this function is the thing that pulls the whole game together, and thus, it is probably the most confusing. Here's what it does: + +- Initializes pygame and the screen +- defines objects and their views and puts them in appropriate arrays +- defines controller +- Runs main while loop, which updates object positions, draws the corresponding views, and checks for events. This stops running if the player dies or closes the window. +- If the player dies, it runs another while loop which displays the losing screen. + +And that's it! + +## So how do I play? +Assuming you're working in Linux, it's really as simple as installing Pygame, downloading playfile.py, and calling it in Python using your terminal. This is what this will look like in your command window: + +First, +``` +pip install pygame +``` +Next, +``` +python playfile.py +``` +And look out, because now you're playing! + +If you run into some issues installing Pygame or even Python, [this is a nice guide to refer to](https://www.pygame.org/wiki/GettingStarted). + +## Other questions + +#### It's running too slow, what can I do to fix it? +Try lowering the mod on the counter in the first if statement of the main while loop. For example, try turning this: + +``` +while running == True: + counter += 1 + if counter%5 == 0: # adjust this + controller.handle_event() +``` +into this: +``` +while running == True: + counter += 1 + if counter%2 == 0: # adjust this + controller.handle_event() +``` +Beyond that, this really isn't the most efficient thing in the world right now... sorry about that. + +#### Why do I always lose? +Life isn't fair, buddy. Neither is this. + +## License +Hmm. \ No newline at end of file diff --git a/playfile.py b/playfile.py index 3abb265..ec7e101 100644 --- a/playfile.py +++ b/playfile.py @@ -1,22 +1,8 @@ -"""main.py - -objects: screen, player, follower - -TODO: -- train constant speed -- player slows down -- lose on collision -- flat level - -DONE: -- simple objects for player sprite""" +"""Pain Train the Video Game, by Charlie Weiss and Diego Garcia""" import pygame import math -# Images -gameover = pygame.image.load('gameover1.bmp') - # Colors BLACK = (0,0,0) WHITE = (255,255,255) @@ -47,7 +33,13 @@ def go_back(self): return self.x < 130 def hit_ground(self,ground): - return (self.y + self.height) > ground.y + return (self.y + self.height) > ground.y and self.x < (ground.x+ground.width) and self.x > ground.x + + def fall_to_death(self): + return self.y > 480 + + def on_ground(self,ground): + return self.x < (ground.x+ground.width) and self.x > ground.x class PainTrain(object): def __init__(self,x=0,y=0,width=200,height=200,constdx=.05,dx=0,shiftdx=-1): @@ -149,9 +141,12 @@ def main(): pygame.init() screen = pygame.display.set_mode((640,480)) + # Images + gameover = pygame.image.load('gameover1.bmp').convert() + # models # level models: - ground = Ground() + ground = Ground(width=1500) #x=0? platform1 = Platform(10,10) platform2 = Platform(800,10) platform3 = Platform(1600,10) @@ -175,7 +170,7 @@ def main(): views.append(ObstacleView(platform4)) views.append(ObstacleView(platform5)) - # TODO: Add controller + # controller controller = Controller(controlled_models) running = True counter = 0 @@ -184,16 +179,15 @@ def main(): delta_speed = .00005 # good one is .00005 while running == True: - # Pretty awful way to slow player down. - counter += 1 # adjust this if it's running to slow. Sorry. - if counter%5 == 0: + counter += 1 + if counter%5 == 0: # adjust this if it's running too slow. A little jank, sorry. controller.handle_event() for event in pygame.event.get(): if event.type == pygame.QUIT: running = False - if player.train_wreck(train): + if player.train_wreck(train) or player.fall_to_death(): train.constdx = 0 player.dx = 0 running = False @@ -202,6 +196,9 @@ def main(): player.dy = 0 player.y = ground.y - player.height + if not player.on_ground(ground) and player.dy==0: + player.dy = .001 + # keep train moving train.step()