Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 135 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -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.
41 changes: 19 additions & 22 deletions playfile.py
Original file line number Diff line number Diff line change
@@ -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)
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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()
Expand Down