From d24cd3861ba4f6c9d21b55301e8c12ecbae4f4a0 Mon Sep 17 00:00:00 2001 From: Miguel Angel Astor Romero Date: Mon, 7 Jan 2013 20:22:23 -0430 Subject: [PATCH] Created the main game loop and started writing the game's states. --- .gitignore | 12 +++++++ LICENSE | 22 +++++++++++++ game.py | 84 ++++++++++++++++++++++++++++++++++++++++++++++++ ingame.py | 41 +++++++++++++++++++++++ intro.py | 41 +++++++++++++++++++++++ main.py | 45 ++++++++++++++++++++++++++ menu.py | 41 +++++++++++++++++++++++ notvalidstate.py | 34 ++++++++++++++++++++ score.py | 41 +++++++++++++++++++++++ state.py | 19 +++++++++++ 10 files changed, 380 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 game.py create mode 100644 ingame.py create mode 100644 intro.py create mode 100644 main.py create mode 100644 menu.py create mode 100644 notvalidstate.py create mode 100644 score.py create mode 100644 state.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d7f270d --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +# Emacs backup files # +###################### +*~ + +# Compiled files # +################## +*.pyo +*.pyc + +# OS Files # +############ +Thumbs.db diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9772459 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2012, Miguel Angel Astor Romero +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + *) Redistributions of source code must retain the above + copyright notice, this list of conditions and the following disclaimer. + *) Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/game.py b/game.py new file mode 100644 index 0000000..d74864e --- /dev/null +++ b/game.py @@ -0,0 +1,84 @@ +# Miguel Angel Astor Romero. Created on 7-1-2012. # +################################################### +import pygame + +try: + import android +except ImportError: + android = None + +from state import VALID_STATES +from intro import IntroState +from menu import MenuState +from ingame import InGameState +from score import ScoreState +from notvalidstate import NotValidState + +# Debug constant. Comment to turn off debugging messages. +DEBUG = True + +# The Game class implements the state machine of the game and +# runs the main game loop. +class Game: + def __init__(self, screen): + """ Sets the rendering canvas and the intial state. """ + self.canvas = screen + self.current_state = VALID_STATES['INTRO'] + self.done = False + self.clock = pygame.time.Clock() + + # Initialize the different game states. + intro = IntroState() + menu = MenuState() + in_game = InGameState() + score = ScoreState() + not_valid = NotValidState() + + # Create a states list. + self.state_vector = [intro, menu, in_game, score, not_valid] + + def get_state(self): + """ Returns the current state of the game. """ + if self.current_state == VALID_STATES['INTRO']: + return "INTRO" + elif self.current_state == VALID_STATES['MENU']: + return "MENU" + elif self.current_state == VALID_STATES['IN_GAME']: + return "IN_GAME" + elif self.current_state == VALID_STATES['SCORE']: + return "SCORE" + elif self.current_state == VALID_STATES['QUIT']: + return "QUIT" + else: + return "NOT_VALID" + + def game_loop(self): + """ The main game loop. """ + while not self.done: + # Get user input first. + self.state_vector[self.current_state].input() + # Then update the game state. + transition = self.state_vector[self.current_state].update() + # Check if a state transition is required. + if transition != VALID_STATES['STAY']: + if transition == VALID_STATES['INTRO']: + self.current_state = VALID_STATES['INTRO'] + elif transition == VALID_STATES['MENU']: + self.current_state = VALID_STATES['MENU'] + elif transition == VALID_STATES['IN_GAME']: + self.current_state = VALID_STATES['IN_GAME'] + elif transition == VALID_STATES['SCORE']: + self.current_state = VALID_STATES['SCORE'] + elif transition == VALID_STATES['QUIT']: + self.done = True + self.current_state = VALID_STATES['QUIT'] + else: + self.current_state = VALID_STATES['NOT_VALID'] + if DEBUG: + print self.get_state() + # If the game is not over, render the current state. + if not self.done: + self.state_vector[self.current_state].render(self.canvas) + pygame.display.update() + self.clock.tick(60) + diff --git a/ingame.py b/ingame.py new file mode 100644 index 0000000..5190d6d --- /dev/null +++ b/ingame.py @@ -0,0 +1,41 @@ +# Miguel Angel Astor Romero. Created on 7-1-2012. # +################################################### +import pygame + +try: + import android +except ImportError: + android = None + +from state import BaseState, VALID_STATES + +class InGameState(BaseState): + def __init__(self): + self.count = 0 + self.rectangle = pygame.Rect(250, 350, 100, 100) + self.next_transition = VALID_STATES['STAY'] + + def input(self): + for event in pygame.event.get(): + if android: + if android.check_pause(): + android.wait_for_resume() + + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_ESCAPE: + self.next_transition = VALID_STATES['QUIT'] + if event.type == pygame.QUIT: + self.next_transition = VALID_STATES['QUIT'] + + def update(self): + if self.next_transition != VALID_STATES['QUIT']: + if self.count < 120: + self.count += 1 + self.next_transition = VALID_STATES['STAY'] + else: + self.count = 0 + self.next_transition = VALID_STATES['SCORE'] + return self.next_transition + + def render(self, canvas): + pygame.draw.rect(canvas, (255, 0, 255), self.rectangle) diff --git a/intro.py b/intro.py new file mode 100644 index 0000000..ed98e3d --- /dev/null +++ b/intro.py @@ -0,0 +1,41 @@ +# Miguel Angel Astor Romero. Created on 7-1-2012. # +################################################### +import pygame + +try: + import android +except ImportError: + android = None + +from state import BaseState, VALID_STATES + +class IntroState(BaseState): + def __init__(self): + self.count = 0 + self.rectangle = pygame.Rect(250, 350, 100, 100) + self.next_transition = VALID_STATES['STAY'] + + def input(self): + for event in pygame.event.get(): + if android: + if android.check_pause(): + android.wait_for_resume() + + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_ESCAPE: + self.next_transition = VALID_STATES['QUIT'] + if event.type == pygame.QUIT: + self.next_transition = VALID_STATES['QUIT'] + + def update(self): + if self.next_transition != VALID_STATES['QUIT']: + if self.count < 120: + self.count += 1 + self.next_transition = VALID_STATES['STAY'] + else: + self.count = 0 + self.next_transition = VALID_STATES['MENU'] + return self.next_transition + + def render(self, canvas): + pygame.draw.rect(canvas, (255, 255, 255), self.rectangle) diff --git a/main.py b/main.py new file mode 100644 index 0000000..4c6b177 --- /dev/null +++ b/main.py @@ -0,0 +1,45 @@ +# Miguel Angel Astor Romero. Created on 7-1-2012. # +################################################### +import pygame + +try: + import android +except ImportError: + android = None + +from game import Game + +def main(): + """ Initializes PyGame and pgs4a and starts the game loop. """ + # Variables. + screen = None + + # Init PyGame. + pygame.init() + + if android: + # Init pgs4a and map Android's back button to PyGame's escape key. + android.init() + android.map_key(android.KEYCODE_BACK, pygame.K_ESCAPE) + # Get the device's screen size and request a surface of that size. + screen_size = (pygame.display.Info().current_w, + pygame.display.Info().current_h) + screen = pygame.display.set_mode(screen_size) + else: + # If not on Android, default to a 800x600 pixels screen. + screen = pygame.display.set_mode((800, 600)) + pygame.display.set_caption("Super HUGS Revolution 98") + + # Create the main game object. + game = Game(screen) + + # Start the game. + print game.get_state() + game.game_loop() + + # Cleanly terminate PyGame. + pygame.quit() + +# Required by pgs4a. +if __name__ =="__main__": + main() diff --git a/menu.py b/menu.py new file mode 100644 index 0000000..64fa3de --- /dev/null +++ b/menu.py @@ -0,0 +1,41 @@ +# Miguel Angel Astor Romero. Created on 7-1-2012. # +################################################### +import pygame + +try: + import android +except ImportError: + android = None + +from state import BaseState, VALID_STATES + +class MenuState(BaseState): + def __init__(self): + self.count = 0 + self.rectangle = pygame.Rect(250, 350, 100, 100) + self.next_transition = VALID_STATES['STAY'] + + def input(self): + for event in pygame.event.get(): + if android: + if android.check_pause(): + android.wait_for_resume() + + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_ESCAPE: + self.next_transition = VALID_STATES['QUIT'] + if event.type == pygame.QUIT: + self.next_transition = VALID_STATES['QUIT'] + + def update(self): + if self.next_transition != VALID_STATES['QUIT']: + if self.count < 120: + self.count += 1 + self.next_transition = VALID_STATES['STAY'] + else: + self.count = 0 + self.next_transition = VALID_STATES['IN_GAME'] + return self.next_transition + + def render(self, canvas): + pygame.draw.rect(canvas, (0, 255, 255), self.rectangle) diff --git a/notvalidstate.py b/notvalidstate.py new file mode 100644 index 0000000..402ad89 --- /dev/null +++ b/notvalidstate.py @@ -0,0 +1,34 @@ +# Miguel Angel Astor Romero. Created on 7-1-2012. # +################################################### +import pygame + +try: + import android +except ImportError: + android = None + +from state import BaseState, VALID_STATES + +class NotValidState(BaseState): + def __init__(self): + self.count = 0 + self.rectangle = pygame.Rect(250, 350, 100, 100) + self.next_transition = VALID_STATES['STAY'] + + def input(self): + for event in pygame.event.get(): + if android: + if android.check_pause(): + android.wait_for_resume() + + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_ESCAPE: + self.next_transition = VALID_STATES['QUIT'] + if event.type == pygame.QUIT: + self.next_transition = VALID_STATES['QUIT'] + + def update(self): + return self.next_transition + + def render(self, canvas): + pygame.draw.rect(canvas, (0, 0, 0), self.rectangle) diff --git a/score.py b/score.py new file mode 100644 index 0000000..3f0c33b --- /dev/null +++ b/score.py @@ -0,0 +1,41 @@ +# Miguel Angel Astor Romero. Created on 7-1-2012. # +################################################### +import pygame + +try: + import android +except ImportError: + android = None + +from state import BaseState, VALID_STATES + +class ScoreState(BaseState): + def __init__(self): + self.count = 0 + self.rectangle = pygame.Rect(250, 350, 100, 100) + self.next_transition = VALID_STATES['STAY'] + + def input(self): + for event in pygame.event.get(): + if android: + if android.check_pause(): + android.wait_for_resume() + + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_ESCAPE: + self.next_transition = VALID_STATES['QUIT'] + if event.type == pygame.QUIT: + self.next_transition = VALID_STATES['QUIT'] + + def update(self): + if self.next_transition != VALID_STATES['QUIT']: + if self.count < 120: + self.count += 1 + self.next_transition = VALID_STATES['STAY'] + else: + self.count = 0 + self.next_transition = VALID_STATES['MENU'] + return self.next_transition + + def render(self, canvas): + pygame.draw.rect(canvas, (255, 255, 0), self.rectangle) diff --git a/state.py b/state.py new file mode 100644 index 0000000..915a3ea --- /dev/null +++ b/state.py @@ -0,0 +1,19 @@ +# Miguel Angel Astor Romero. Created on 7-1-2012. # +################################################### + +# Valid game states. +VALID_STATES = { 'INTRO':0, 'MENU':1, 'IN_GAME':2, 'SCORE':3, 'STAY':4, 'QUIT':89} + +# Parent class for game states. +class BaseState: + def input(self): + """ Empty. Should handle PyGame input. """ + pass + + def update(self): + """ Empty. Should update the state. Returns a state to transition to. """ + return VALID_STATES['STAY'] + + def render(self, canvas): + """ Empty. Should render this state on the canvas. """ + pass