#!/usr/bin/python # -*- coding: iso8859-15 -*- # first shoot'em um prototype # may be ported to DS later # it will use pygame (at least at the beginning) for input handling, graphics and sound import pygame from pygame.locals import * import os import random from math import sqrt,pow,ceil,floor # constants SCREEN_X = 640 SCREEN_Y = 480 class Globals: def __init__(self): self.screen = None self.background = None self.level_event_list = [] self.clock = None self.event_type = {} self.die = False self.moving_objects = pygame.sprite.RenderUpdates() self.bullets_list = pygame.sprite.RenderUpdates() self.bullets_list_player = pygame.sprite.RenderUpdates() self.bullet_factory = BulletFactory() self.enemies_list = pygame.sprite.RenderUpdates() self.enemies_active_list = pygame.sprite.RenderUpdates() self.enemy_factory = EnemyFactory() self.player = None self.players_list = pygame.sprite.RenderUpdates() class Event_Spawn: def __init__(self, enemy_type, pos): self.time = 0 self.enemy_type = 0 self.pos = pos def activate(self): e = globals.enemy_factory.create(self.enemy_type, self.pos) globals.enemies_list.add(e) globals.enemies_active_list.add(e) class Object(pygame.sprite.Sprite): def __init__(self, frames, pos, speed): pygame.sprite.Sprite.__init__(self) self.speed = speed self.frames = frames self.frames_index = 0 self.image = None self.load() self.rect = self.image.get_rect().move(pos) def load(self): """ load sprite list """ index = 0 for f in self.frames: image = pygame.image.load(os.path.join('data', f)).convert() image.set_colorkey(pygame.Color(255,255,255, 0)) self.frames[index] = image index += 1 self.image = self.frames[self.frames_index] def update(self): self.rect.move_ip(self.speed) class BulletFactory(): """ BulletFactory, create bullets """ def create(self, type, pos, wavepos): """ create bullt of type type wave paremeter indicate the position of the bullet in the wave : starting the wave (0), middle (1) or ending the wave (2 )""" if type == 0: return self.create_type0(pos) if type == 1: return self.create_type1(pos, wavepos) def create_type0(self, pos): """ create a bullet of type 0 temporary linear type """ bullet = Bullet(['bullet.bmp'], 0, pos) bullet.speed = (10,0) bullet.damage = 10 return bullet def create_type1(self, pos, wavepos): """ create a bullet of type 1 temporary laser type """ filename = 'laser' + str(wavepos + 1) + '.bmp' #print "filename: " + filename #filename = 'laser1.bmp' bullet = Bullet([filename], 0, pos) bullet.speed = (10,0) bullet.damage = 10 return bullet def create_type2(self, pos, speed): """ create a bullet of type 2 temporary ennemies bullet """ bullet = Bullet(['bullet_red.bmp'], 0, pos) bullet.speed = speed bullet.damage = 10 return bullet def create_type3(self, pos, speed): """ create a bullet of type 3 temporary ennemies bullet (aiming) """ bullet = Bullet(['bullet_purple.bmp'], 0, pos) bullet.speed = speed bullet.damage = 10 return bullet class Bullet(Object): def __init__(self, frames, type, pos): Object.__init__(self, frames, pos, (0, 0)) self.type = type # recenter the sprite # self.rect = self.rect.move((0, - self.rect.height / 2)) self.rect = self.rect.move((-32, - self.rect.height / 2)) def update(self): # destroy when collide or when exists the screen if self.in_screen(): self.rect.move_ip(self.speed) else: globals.bullets_list.remove(self) def in_screen(self): """ detect if bullet is in the screen """ return self.rect.colliderect(globals.screen.get_rect()) class Player(Object): def __init__(self, frames, pos, speed): Object.__init__(self, frames, pos, speed) self.shooting = False self.bullet_type = 0 self.bullet_counter = 0 self.bullet_threshold = 5 def shoot(self): """ create a bullet and add it to the global bullet list""" bullet = globals.bullet_factory.create(self.bullet_type, self.rect.midright, self.shoot_wavepos) if self.shoot_wavepos == 0: self.shoot_wavepos = 1 if self.shoot_wavepos == 2: self.shoot_wavepos = 0 self.shooting = False globals.bullets_list_player.add(bullet) def start_move(self, vector): """ initiate moving sequence """ globals.moving_objects.add(self) self.speed = (self.speed[0] + vector[0], self.speed[1] + vector[1]) self.image = self.frames[1] def stop_move(self, vector): """ stop moving sequence """ self.speed = (self.speed[0] - vector[0], self.speed[1] - vector[1]) if self.speed == (0, 0): globals.moving_objects.remove(self) self.image = self.frames[0] def start_shoot(self): self.shooting = True self.shoot_wavepos = 0 def stop_shoot(self): self.shoot_wavepos = 2 def change_bullet_type(self): self.bullet_type ^= 1 def update(self): self.rect.move_ip(self.speed) if self.shooting: if self.bullet_counter == self.bullet_threshold: self.shoot() self.bullet_counter = 0 else: self.bullet_counter += 1 class EnemyFactory: """ Enemy Factory - Creates Enemy """ def __init__(self): pass def create(self, type, pos): if type == 0: return self.create_type0(pos) def create_type0(self, pos): e = Enemy(['enemy1_1.bmp', 'enemy1_2.bmp', 'enemy1_3.bmp', 'enemy1_4.bmp', 'enemy1_5.bmp', 'enemy1_6.bmp'], 0, pos) return e class Enemy(Object): def __init__(self, frames, type, pos): Object.__init__(self, frames, pos, (-1, 0)) self.counter = 0 self.counter_fire = 0 self.threshold = 2 self.threshold_fire = 100 self.dying = False def update(self): if self.counter == self.threshold: if self.dying: self.frames_index += 1 if self.frames_index == 6: globals.enemies_list.remove(self) return self.image = self.frames[self.frames_index] else: self.rect.move_ip(self.speed) self.counter = 0 else: self.counter += 1 if not self.dying: if self.counter_fire == self.threshold_fire: self.shoot_player() self.counter_fire = 0 else: self.counter_fire += 1 def shoot_player(self): """ shoot a bullet to the player """ speed = self.aim() bullet = globals.bullet_factory.create_type2(self.rect.midleft, speed) globals.bullets_list.add(bullet) def aim_player(self): """ compute speed vector to aim at current player position """ # get player position localspeed = 5 player_pos = globals.player.rect direction = (player_pos[0] - self.rect[0], player_pos[1] - self.rect[1]) norm = sqrt(pow(direction[0], 2) + pow(direction[1], 2)) speed = (direction[0] / norm, direction[1] / norm) speed2 = (ceil(speed[0] * localspeed), floor(speed[1]) * localspeed) print "direction: " + str(direction) print "norm: " + str(norm) print "speed: " + str(speed) print "speed2: " + str(speed2) print return speed2 def aim(self): """ set bullet speed """ return self.aim_player() # return (-10, 0) def die(self): """ make the enemy dying """ self.dying = True self.threshold = 5 self.frames_index = 2 self.image = self.frames[self.frames_index] globals.enemies_active_list.remove(self) def init_gfx(): """graphics initialisation""" globals.screen = pygame.display.set_mode((SCREEN_X, SCREEN_Y), HWSURFACE|DOUBLEBUF) globals.screen.fill(0) pygame.display.flip() def init_sound(): """sound initialisation""" pass def init(): """ general initialisation""" pygame.init() pygame.display.set_caption('Pyshoot') pygame.mouse.set_visible(0) init_gfx() globals.clock = pygame.time.Clock() random.seed() #globals.event_type = {'create_enemeny' : create_enemey, 'vanish_object': vanish_object()} class Level(): """ Level holder """ def __init__(self): self.event_list = [] self.past_event_list = [] self.next_event = 0 self.create_level1() def create_level1(self): """ phony level one""" # create events # dict events string => function # for e in keys(globals.events_type): self.event_list.insert(0, (50, Event_Spawn(0, (500,200)) ) ) self.event_list.insert(0, (150, Event_Spawn(0, (500,100)) ) ) self.event_list.insert(0, (150, Event_Spawn(0, (500,200)) ) ) self.event_list.insert(0, (250, Event_Spawn(0, (500,100)) ) ) self.event_list.insert(0, (250, Event_Spawn(0, (500,200)) ) ) self.event_list.insert(0, (250, Event_Spawn(0, (500,300)) ) ) self.next_event, event = self.event_list[-1] print "next : " + str(self.next_event) def update(self, nbframe): # print "(next, frame) : (" + str(self.next_event) + ", " + str(self.next_event) + ")" while nbframe == self.next_event: event_tuple = self.event_list.pop() frame, event = event_tuple event.activate() self.past_event_list.append(event) #self.event_list.remove(event_tuple) if len(self.event_list) > 0: self.next_event, event = self.event_list[-1] else: # no more event self.end() self.next_event = 0 def end(self): """ end of level """ pass def wait_keypress(): """ wait for a keypress and then return """ next = 0 while next != 1: for event in pygame.event.get(): if event.type == KEYDOWN: next = 1 def process_key(event, player): """ process keyboard input """ if event.type == KEYDOWN: if event.key == K_ESCAPE: globals.die = True elif event.key == K_UP: player.start_move((0, -1)) elif event.key == K_DOWN: player.start_move((0, 1)) elif event.key == K_LEFT: player.start_move((-1, 0)) elif event.key == K_RIGHT: player.start_move((1, 0)) elif event.key == K_x: player.start_shoot() elif event.key == K_e: e = Enemy(['enemy1_1.bmp', 'enemy1_2.bmp', 'enemy1_3.bmp', 'enemy1_4.bmp', 'enemy1_5.bmp', 'enemy1_6.bmp'], 0, (500, 200)) globals.enemies_list.add(e) globals.enemies_active_list.add(e) elif event.key == K_SPACE: player.change_bullet_type() if event.type == KEYUP: if event.key == K_UP: player.stop_move((0, -1)) elif event.key == K_DOWN: player.stop_move((0, 1)) elif event.key == K_LEFT: player.stop_move((-1, 0)) elif event.key == K_RIGHT: player.stop_move((1,0)) elif event.key == K_x: player.stop_shoot() def transition(type): """ transition selector """ if type == 0: transition_disintegrate() elif type == 1: transition_fade_to_black() elif type == 2: transition_fade_to_white() def transition_disintegrate(): """ put black pixels at randoom location""" for i in range(0, 200000): x = random.randint(0, SCREEN_X) y = random.randint(0, SCREEN_Y) globals.screen.set_at((x, y), (0,0,0, 255)) if i % 1000 == 0 : pygame.display.update() globals.screen.fill((0, 0, 0)) pygame.display.update() def transition_fade_to_black(): """ darken every pixels on screen """ array = pygame.PixelArray(globals.screen) pass def transition_fade_to_white(): """ lighten every pixels on screen """ pass def handle_enemies_collisions(collisions): """ take the returned dictionnary from pygame.sprite.groupcollide()""" for bullet, enemies in collisions.iteritems(): if enemies != []: for e in enemies: e.die() globals.bullets_list_player.remove(bullet) def handle_player_collisions(collisions): """ take the returned dictionnary from pygame.sprite.groupcollide()""" for bullet, enemies in collisions.iteritems(): # show some player reaction ;-) globals.bullets_list.remove(bullet) ## # Main ## globals = Globals() init() wait_keypress() nbframe = 0 # initialize level level = Level() # create_player player = Player(['player1_1.bmp', 'player1_2.bmp'], (50, 50), (0, 0)) globals.player = player globals.players_list.add(player) # background globals.background = pygame.image.load(os.path.join('data', 'background1.bmp')).convert() background_rect = globals.background.get_rect() globals.screen.blit(globals.background, background_rect) pygame.display.flip() # draw initial sprite globals.moving_objects.add(player) while not globals.die: # erase previously moved objects globals.moving_objects.clear(globals.screen, globals.background) globals.bullets_list.clear(globals.screen, globals.background) globals.bullets_list_player.clear(globals.screen, globals.background) globals.enemies_list.clear(globals.screen, globals.background) # update game logic globals.moving_objects.update() globals.bullets_list.update() globals.bullets_list_player.update() globals.enemies_list.update() # collisions ret = pygame.sprite.groupcollide(globals.bullets_list_player, globals.enemies_active_list, False, False) handle_enemies_collisions(ret) ret = pygame.sprite.groupcollide(globals.bullets_list, globals.players_list, False, False) handle_player_collisions(ret) # add player (if it's not already in the group). ugly, but ok for now. globals.moving_objects.add(player) # drawing rectlist = globals.moving_objects.draw(globals.screen) rectlist.extend(globals.bullets_list.draw(globals.screen)) rectlist.extend(globals.bullets_list_player.draw(globals.screen)) rectlist.extend(globals.enemies_list.draw(globals.screen)) pygame.display.update(rectlist) # pygame.display.flip() nbframe = nbframe + 1 # do level things level.update(nbframe) globals.clock.tick(60) for event in pygame.event.get(): if event.type == KEYDOWN or event.type == KEYUP: process_key(event, player) # reinitializing moving objects list #globals.moving_objects = pygame.sprite.RenderUpdates() #transition(0) print "frames : %d" % nbframe # TODO: # + Objects / Sprites # --> convert my Objects to pygame.sprite.Sprite # --> convert moving_objects list to Group # + Input # --> handle continuous keypress # + Movving Sprites # --> handle continous player move (related to Input) # --> Sprites (non related to player input) movement vector, etc...