habe nun an meinem 8-Bit Panzergeballere - Klon gebastelt und habe einige Ratschläge umgesetzt, welche ich hier erhielt.
Macht eigentlich jetzt schon Spass das ganze finde ich , und läuft jetzt auch flüssig
Nun habe ich aber mal fragen wollen, wie ihr das so seht bzgl. Programmstruktur. Wer mag kann sich mal mein Prog anschauen - ist eigentlich noch ganz übersichltich soweit:
Code: Alles auswählen
import sys, pygame, os, random, time
sys.path.append("""C:\Python25\Game Development\System""")
pygame.mixer.pre_init(44100,-16,2, 1024)
pygame.init()
from pygame.locals import *
NES_RES = (512, 480)
RES = (640, 480)
SCREEN = pygame.display.set_mode(RES, FULLSCREEN, 32)
from sprite import My_Sprite
from farben import *
from grafik import *
from sound import sound_laden, play_music
from gamepads import Gamepad, get_gamepad_ids
from tanks import Tank
from tank_levels import levels
from tank_map import Map
class Game():
def __init__(self):
self.tick = 10
self.SCREEN = SCREEN
self.RES = RES
self.u = 24
self.intro_on = False
self.black_screen = pygame.Surface(self.RES)
self.black_screen.fill(schwarz)
self.titelbild = bild_laden("Title Screens", "pixel_tanks.png", True)
self.levels = levels
self.level = 1
self.map = Map(self.RES, self.u)
self.map.init_tiles(self.levels[self.level])
self.gamepads = []
self.tanks = []
self.gamepad_ids = get_gamepad_ids()
self.nr_of_players = len(self.gamepad_ids)
for pad_id in self.gamepad_ids:
gamepad = Gamepad(pad_id)
self.gamepads.append(gamepad)
tank = Tank(gamepad, self.u)
tank.init_map(self.map)
self.tanks.append(tank)
for tank in self.tanks:
for gegner_tank in self.tanks:
if gegner_tank != tank:
tank.gegnerliste.append(gegner_tank)
self.hintergrund = self.black_screen
def check_quit(self):
self.events = pygame.event.get()
for event in self.events:
if event.type == QUIT or event.type == KEYDOWN and event.key == K_ESCAPE:
pygame.quit()
sys.exit()
def get_standbild(self):
self.standbild = pygame.Surface(self.RES)
self.standbild.blit(self.SCREEN, (0, 0))
def blit_hintergrund(self):
self.SCREEN.blit(self.hintergrund, (0, 0))
def einblenden(self, speed = -2.5):
"""Szene, die das Bild einblendet. speed = 2.5 (langsam)"""
self.get_standbild()
alpha = 255
alpha_min = 0
for a in range(alpha, alpha_min, speed):
self.check_input()
self.black_screen.set_alpha(a)
self.SCREEN.blit(self.standbild, (0, 0))
self.SCREEN.blit(self.black_screen, (0, 0))
self.slow_motion()
self.black_screen.set_alpha(255)
def ausblenden(self, speed = 2.5, wait_time = 0):
"""Szene, die das Bild ausblendet. speed = 2.5 (langsam), wait_time = Wartezeit nach Ausblende"""
self.get_standbild()
alpha = 0
alpha_max = 255
for a in range(alpha, alpha_max, speed):
self.check_input()
self.black_screen.set_alpha(a)
self.SCREEN.blit(self.standbild, (0, 0))
self.SCREEN.blit(self.black_screen, (0, 0))
self.slow_motion()
if wait_time > 0:
self.wait(wait_time)
def intro(self):
if self.intro_on:
self.SCREEN.blit(self.titelbild, (0, 0))
self.einblenden()
self.wait(50)
self.ausblenden(5)
self.wait(50)
def run(self):
pygame.mouse.set_visible(0)
while True:
t_before = pygame.time.get_ticks()
self.blit_hintergrund()
self.check_quit()
for pad in self.gamepads:
pad.check_input()
for tank_x in self.tanks[:]:
tank_x.update()
if tank_x.remove_me:
self.tanks.remove(tank_x)
for shot in tank_x.shots:
self.SCREEN.blit(shot.bild, shot.rect)
self.SCREEN.blit(tank_x.bild, tank_x.rect)
for tile in self.map.tiles.values():
self.SCREEN.blit(tile.bild, tile.rect)
pygame.display.flip()
t_after = pygame.time.get_ticks()
t_passed = t_after - t_before
wait_time = self.tick - t_passed
pygame.time.wait(wait_time)
new_game = Game()
new_game.run()
pygame.quit()
sys.exit()
Code: Alles auswählen
levels = {}
levels[1] = {
"stahl" : [(4, 4), (5, 4), (6, 4), (7, 4),
(4, 5), (5, 5), (6, 5), (7, 5),
(4, 6), (5, 6), (4, 7), (5, 7),
(17, 4), (18, 4), (19, 4), (20, 4),
(17, 5), (18, 5), (19, 5), (20, 5),
(19, 6), (20, 6), (19, 7), (20, 7),
(4, 11), (5, 11), (4, 12), (5, 12),
(4, 13), (5, 13), (6, 13), (7, 13),
(4, 14), (5, 14), (6, 14), (7, 14),
(19, 11), (20, 11), (19, 12), (20, 12),
(17, 13), (18, 13), (19, 13), (20, 13),
(17, 14), (18, 14), (19, 14), (20, 14)],
"stein" : [(8, 4), (9, 4), (10, 4), (11, 4), (12, 4), (13, 4), (14, 4), (15, 4), (16, 4),
(8, 5), (9, 5), (10, 5), (11, 5), (12, 5), (13, 5), (14, 5), (15, 5), (16, 5),
(8, 13), (9, 13), (10, 13), (11, 13), (12, 13), (13, 13), (14, 13), (15, 13), (16, 13),
(8, 14), (9, 14), (10, 14), (11, 14), (12, 14), (13, 14), (14, 14), (15, 14), (16, 14),
(4, 8), (5, 8), (4, 9), (5, 9), (4, 10), (5, 10),
(19, 8), (20, 8), (19, 9), (20, 9), (19, 10), (20, 10)],
"tarntile" : [(6, 6), (7, 6), (6, 7), (7, 7),
(6, 11), (7, 11), (6, 12), (7, 12),
(17, 6), (18, 6), (17, 7), (18, 7),
(17, 11), (18, 11), (17, 12), (18, 12)]}
Code: Alles auswählen
from map_tiles import Tile
class Map():
def __init__(self, res, u):
self.RES = res
self.u = u
self.x_tiles = res[0] / u - 1 # maximale x_tiles
self.y_tiles = res[1] / u - 1 # maximale y_tiles
self.alle_tilepos = [] # Blitpositionen aller Tiles
for y in range(0, self.y_tiles + 1):
for x in range(0, self.x_tiles + 1):
blit_x = x * u
blit_y = y * u
self.alle_tilepos.append((blit_x, blit_y))
self.tiles = {} # noch keine Tiles vorhanden
def init_tiles(self, level):
for tiletyp in level.keys():
for pos in level[tiletyp]:
topleft = (pos[0] * self.u, pos[1] * self.u)
tile = Tile(tiletyp, topleft)
self.tiles[topleft] = tile
Code: Alles auswählen
from sprite import My_Sprite
from grafik import bild_laden
ordner = "Tiles"
tile_typen = ("stahl", "stein", "tarntile")
alle_tilebilder = {}
for tile_typ in tile_typen:
if tile_typ != "tarntile":
alle_tilebilder[tile_typ] = bild_laden(ordner, tile_typ + ".png")
else:
alle_tilebilder[tile_typ] = bild_laden(ordner, tile_typ + ".png", True)
class Tile(My_Sprite):
def __init__(self, typ, topleft):
self.typ = typ
tilebild = alle_tilebilder[typ]
centerpos = (topleft[0] + tilebild.get_width() / 2, topleft[1] + tilebild.get_height() / 2)
My_Sprite.__init__(self, tilebild, centerpos)
self.remove_me = False
if typ == "stahl":
self.zerstoerbar = False
self.passierbar = False
elif typ == "stein":
self.zerstoerbar = True
self.passierbar = False
elif typ == "tarntile":
self.zerstoerbar = False
self.passierbar = True
Code: Alles auswählen
from sprite import My_Sprite
from grafik import bild_laden, bild_spiegeln, bild_drehen
from sound import sound_laden
from farben import *
from tank_shots import Panzer_Shot
class Tank(My_Sprite):
max_level = 3
max_players = 4
bildordner = "Characters\\The Good\\Panzer"
images = {}
image_types = ("a", "b")
levels = range(1, max_level + 1)
players = range(1, max_players + 1)
directions = (8, 6, 2, 4)
for player in players:
images[player] = {}
for lvl in levels:
images[player][lvl] = {}
for direction in directions:
images[player][lvl][direction] = []
if direction == 8:
for image_type in image_types:
bild = bild_laden(bildordner, "tank_" + str(player) + "_lvl" + str(lvl) + "_" + image_type + ".png", True)
images[player][lvl][direction].append(bild)
elif direction == 6:
for bild_n in images[player][lvl][8]:
bild = bild_drehen(bild_n, 90)
images[player][lvl][direction].append(bild)
elif direction == 2:
for bild_n in images[player][lvl][6]:
bild = bild_drehen(bild_n, 90)
images[player][lvl][direction].append(bild)
else:
for bild_n in images[player][lvl][2]:
bild = bild_drehen(bild_n, 90)
images[player][lvl][direction].append(bild)
images[player]["explosion"] = bild_laden("Shots", "panzer_explode.png", True)
def __init__(self, gamepad, u):
self.u = u
self.gamepad = gamepad
self.shoot_button = self.gamepad.buttons["button_4"]
self.id = self.gamepad.id
self.player_id = self.id + 1
self.images = Tank.images[self.player_id]
self.bild_index = 0
self.level = 1
self.max_level = Tank.max_level
self.speed = 1
self.max_shots = 1
if self.player_id == 1:
self.dir = 6
self.startpos = (80, 200)
elif self.player_id == 2:
self.dir = 4
self.startpos = (560, 280)
elif self.player_id == 3:
self.dir = 2
self.startpos = (280, 80)
else:
self.dir = 8
self.startpos = (360, 400)
My_Sprite.__init__(self, self.images[self.level][self.dir][self.bild_index], self.startpos)
self.animation_counter = 0
self.animation_trigger = 3
self.shots = []
self.gegnerliste = []
self.hit = False
self.remove_me = False
self.explosion_sound = sound_laden("Defender Sounds", "photon_cannon_impact.wav")
self.explosion_sound.set_volume(0.5)
self.shot_sound = sound_laden("Defender Sounds", "blobfighter_attack.wav")
self.brumm_sound = sound_laden("Sound FX", "mario_level_done.wav")
def init_map(self, map_object):
self.map = map_object
def move(self):
if not self.hit:
digital_pos = self.gamepad.digital_pos
dig_x = digital_pos[0]
dig_y = digital_pos[1]
if dig_x == 1:
self.rect.centerx += self.speed
self.dir = 6
elif dig_x == -1:
self.rect.centerx -= self.speed
self.dir = 4
elif dig_y == 1:
self.rect.centery -= self.speed
self.dir = 8
elif dig_y == -1:
self.rect.centery += self.speed
self.dir = 2
self.bildrand_check()
def bildrand_check(self):
if self.rect.left < 0:
self.rect.left = 0
elif self.rect.right > 640:
self.rect.right = 640
if self.rect.top < 0:
self.rect.top = 0
elif self.rect.bottom > 480:
self.rect.bottom = 480
def bild_update(self):
if not self.hit:
digital_pos = self.gamepad.digital_pos
dig_x = digital_pos[0]
dig_y = digital_pos[1]
if dig_x or dig_y:
self.animation_counter += 1
if self.animation_counter > self.animation_trigger:
self.animation_counter = 0
if self.bild_index < 1:
self.bild_index += 1
else:
self.bild_index = 0
self.set_bild(self.images[self.level][self.dir][self.bild_index])
else:
if self.bild != self.images["explosion"]:
self.set_bild(self.images["explosion"])
self.animation_counter = -1
self.animation_counter += 1
if self.animation_counter >= self.animation_trigger:
self.remove_me = True
def shot_update(self):
for shot in self.shots[:]:
shot.update()
if shot.remove_me:
self.shots.remove(shot)
del shot
def shoot(self):
if not self.hit:
self.gamepad.get_ready("button_4")
if self.shoot_button.ready:
if self.shoot_button.pressed:
if len(self.shots) < self.max_shots:
self.shoot_button.ready = False
shot = Panzer_Shot(self)
self.shots.append(shot)
def collision_checkpos_update(self):
"""merkt sich die 3 relevanten Punkte des Panzer-Rects,
mit welchen die relevanten Tiles für die Rect-Kollision
berechnet und in self.ground_tiles aufgenommen werden können"""
if self.dir == 8:
self.collision_checkpos = [self.rect.topleft, self.rect.midtop, self.rect.topright]
elif self.dir == 6:
self.collision_checkpos = [self.rect.topright, self.rect.midright, self.rect.bottomright]
elif self.dir == 2:
self.collision_checkpos = [self.rect.bottomleft, self.rect.midbottom, self.rect.bottomright]
else:
self.collision_checkpos = [self.rect.topleft, self.rect.midleft, self.rect.bottomleft]
def get_ground_tiles(self):
if not self.hit:
self.collision_checkpos_update()
self.ground_tiles = []
for pos in self.collision_checkpos:
tile_topleft = (pos[0] / self.u * self.u, pos[1] / self.u * self.u)
if self.map.tiles.has_key(tile_topleft):
tile = self.map.tiles[tile_topleft]
if not tile in self.ground_tiles:
if not tile.passierbar:
self.ground_tiles.append(tile)
def tile_collision_check(self):
if not self.hit:
for tile in self.ground_tiles:
if self.front_collision(tile):
if self.dir == 8:
self.rect.top = tile.rect.bottom
elif self.dir == 6:
self.rect.right = tile.rect.left
elif self.dir == 2:
self.rect.bottom = tile.rect.top
else:
self.rect.left = tile.rect.right
def tank_collision_check(self):
if not self.hit:
for gegner in self.gegnerliste:
if self.rect_collision(gegner):
self.hit = gegner.hit = True
def gegnerlisten_update(self):
for gegner in self.gegnerliste[:]:
if gegner.hit:
self.gegnerliste.remove(gegner)
def update(self):
self.gegnerlisten_update()
self.move()
self.shot_update()
self.shoot()
self.bild_update()
self.get_ground_tiles()
self.tile_collision_check()
self.tank_collision_check()
Code: Alles auswählen
from sprite import My_Sprite
from grafik import bild_laden
bild = bild_laden("Shots", "panzer_shot_1.png", True)
class Panzer_Shot(My_Sprite):
def __init__(self, panzer):
self.panzer = panzer
self.map = panzer.map
self.u = self.map.u
self.dir = panzer.dir
self.bild = bild
self.speed = 5
centerpos = self.panzer.rect.center
My_Sprite.__init__(self, self.bild, centerpos)
self.remove_me = False
def move(self):
if self.dir == 6:
self.rect.centerx += self.speed
elif self.dir == 4:
self.rect.centerx -= self.speed
elif self.dir == 8:
self.rect.centery -= self.speed
else:
self.rect.centery += self.speed
if self.rect.left > 640 or self.rect.right < 0 or self.rect.top > 480 or self.rect.bottom < 0:
self.remove_me = True
def tank_collision_check(self):
for gegner in self.panzer.gegnerliste:
if self.rect_collision(gegner):
gegner.hit = True
self.remove_me = True
def tile_collision_check(self):
tile = None
tilepos = (self.rect.centerx / self.u * self.u, self.rect.centery / self.u * self.u)
if self.map.tiles.has_key(tilepos):
tile = self.map.tiles[tilepos]
if tile:
if self.rect_collision(tile):
if not tile.passierbar:
self.remove_me = True
if tile.zerstoerbar:
del self.map.tiles[tile.rect.topleft]
def update(self):
self.move()
self.tank_collision_check()
self.tile_collision_check()
Code: Alles auswählen
# -*- coding: cp1252 -*-
class My_Sprite():
def __init__(self, bild, centerpos):
self.bild = bild
self.rect = bild.get_rect()
self.rect.center = centerpos
def set_bild(self, bild):
self.bild = bild
centerpos = self.rect.center
self.rect = self.bild.get_rect()
self.rect.center = centerpos
def pos_in_rect(self, pos, sprite_object):
rect = sprite_object.rect
if pos[0] > rect.left and pos[0] < rect.right:
if pos[1] > rect.top and pos[1] < rect.bottom:
return True
def front_collision(self, sprite_object):
"""Gibt True zurück, wenn eine der pos in self.collision_checkpos
innerhalb von sprite_object.rect liegt"""
for pos in self.collision_checkpos:
if self.pos_in_rect(pos, sprite_object):
return True
def rect_collision(self, sprite_object):
x_dist = self.rect.centerx - sprite_object.rect.centerx
y_dist = self.rect.centery - sprite_object.rect.centery
if x_dist < 0:
x_dist *= -1
if y_dist < 0:
y_dist *= -1
x_dist -= (self.rect.width / 2 + sprite_object.rect.width / 2)
y_dist -= (self.rect.height / 2 + sprite_object.rect.height / 2)
if x_dist <= 0 and y_dist <= 0:
return True
Im Allgemeinen, was fällt Euch auf, was ich überdenken sollte aus Eurer Sicht? Dies würde mir helfen denke ich, damit ich lerne, schönen objektorientierten Code zu schreiben.
Danke im Voraus - nur schon für's Lesen.
keep on codin',
Henry