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