Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/physics.py
blob: 32aa10ae0e498c6b5cf41d36d2d3cb19257b5c83 (plain)
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#!/usr/bin/python
"""
This file is part of the 'Bridge' Project

Code:   http://git.sugarlabs.org/bridge
        git clone git://git.sugarlabs.org/bridge/mainline.git

This file was originally part of the 'Physics' Project
Physics is a 2D Physics Playground for Kids (supporting Box2D2)
Physics Copyright (C) 2008, Alex Levenson, Brian Jordan
Elements Copyright (C) 2008, The Elements Team, <elements@linuxuser.at>

Wiki:   http://wiki.laptop.org/wiki/Physics
IRC:    #olpc-physics on irc.freenode.org

Code:   http://git.sugarlabs.org/physics
        git clone git://git.sugarlabs.org/physics/mainline.git

License:  GPLv3 http://gplv3.fsf.org/
"""

# Many unused imports, should investigate why
#import sys
#import math

import pygame
from pygame.locals import *
from pygame.color import *
import olpcgames

import elements
#from elements import Elements
import tools
from bridge import Bridge
#from helpers import *

from gettext import gettext as _

class PhysicsGame:
    """
    This class is the actual game that runs.  It sets up the resources needed to run
    and has the loop that handles drawing updates to the screen.
    """
    def __init__(self, screen):
        """
        The constructor for the class.  
        """

        # screen is provided from main() below
        self.screen = screen
        # get everything set up
        self.clock = pygame.time.Clock()
        self.font = pygame.font.Font(None, 24) # font object
        self.canvas = olpcgames.ACTIVITY.canvas # canvas object
        self.joystickobject = None # TODO Figure out why this exists
        self.debug = True  # TODO Figure out what this does.

        self.running = False

        # create the name --> instance map for components
        self.toollist = {}
        for tool in tools.ALLTOOLS:
            self.toollist[tool.name] = tool(self)
        self.currenttool = self.toollist[tools.ALLTOOLS[0].name]
        
        # set up the world (instance of Elements)
        self.world = elements.Elements(self.screen.get_size())
        self.world.renderer.set_surface(self.screen)
        
        # set up static environment
        #self.world.add.ground()
        self.world.run_physics = False

        self.bridge = Bridge(self)
        self.bridge.create_world()
        
    def run(self):
        """This method starts the simulation and provides the loop mechanism.
        """
        self.running = True
        ticks = pygame.time.get_ticks()
        while self.running:
            if (pygame.time.get_ticks() - ticks) > 1500:
#                bridge.create_train(self)
                ticks = pygame.time.get_ticks()
                
            for event in pygame.event.get():
                # Handles events like button clicks
                self.currenttool.handleEvents(event)

            # Clear Display
            self.screen.fill((80, 160, 240)) #255 for white

            # Update & Draw World
            self.world.update()
            self.world.draw()

            # This is True if the simulation is active, meaning
            # the user has requested a train attempt to drive across the bridge.
            if self.world.run_physics:
                self.bridge.for_each_frame()           

            # draw output from tools
            self.currenttool.draw()

            #Print all the text on the screen
            # The underscore function will do translations
            # to native languages if available.
            text = self.font.render(_("Total Cost: %d") % self.bridge.cost,
                True, (0, 0, 0))
            textpos = text.get_rect(left=100, top=7)
            self.screen.blit(text, textpos)
            ratio = self.bridge.stress*100/self.bridge.capacity
            text = self.font.render(_("Stress: %d%%") % ratio, True, (0, 0, 0))
            textpos = text.get_rect(left=100, top=25)
            self.screen.blit(text, textpos)

            if self.bridge.train_off_screen:
                text = self.font.render(
                    _("Train fell off the screen, press R to try again!"), 
                    True, (0, 0, 0))
            elif self.bridge.level_completed:
                text = self.font.render(
                    _("Level completed, well done!!  Press T to send another train."),
                    True, (0, 0, 0))
            else:
                text = self.font.render(
                    _("Press the Spacebar to start/pause."), 
                    True, (0, 0, 0))
            textpos = text.get_rect(left=100, top=43)
            self.screen.blit(text, textpos)

            # Flip Display
            pygame.display.flip()  
            
            # Try to stay at 30 FPS
            self.clock.tick(30) # originally 50    

    def settool(self, tool):
        """Deactivates the previously selected tool, and then sets
        the currenttool to be the specified tool.
        """
        self.currenttool.cancel()
        self.currenttool = self.toolList[tool] 

# main() is a function, by itself.  It is not in a class.
def main():
    """Runs the activity if the file is ran independently.
    See longer comment below.
    """
    toolbarheight = 75 # number of pixels
    tabheight = 45 # number of pixels
    pygame.init() 
    pygame.display.init() 
    xsize, ysize  = pygame.display.list_modes()[0] # function returns an array
    # where the first element [0]  is probably the largest resolution.
    screen = pygame.display.set_mode((xsize, ysize-toolbarheight-tabheight))
    # screen uses the full width, x
    # set the screen height less the space needed for the toolbar and tab.

    # create an instance of the game
    # PhysicsGame is a class (see above in this file)
    game = PhysicsGame(screen) 

    # start the main loop
    # This is where the game actually runs. This method is defined in this file.
    game.run()
# end of main()

# make sure that main() get's called
# This means that the program was run from the command line as
# python physics.py or ./physics.py or similar.
# if the file was loaded from another .py file using the import keyword
# than main() would not be called.
# This is a handy way to provide a classes and functions to a larger program
# while still performing a smaller action on its own usage.
# Also can be handy for testing code.
if __name__ == '__main__':
    main()