Dies ist eine alte Version des Dokuments!
Bomb It mit Python
Wir wollen ein Spiel programmieren, in welchem man mit dem Spieler auf einem Feld herumlaufen kann. Es gibt fixe Hindernisse und auch zerstörbare. Der Spieler kann Bomben platzieren. Bomben zerstören Hindernisse, welche dann Item droppen. Wenn man die Items aufsammelt, bekommt der Spieler ein Upgrade. Das Spiel spielt man zu zweit. Der Spieler der am längsten überlebt gewinnt. Andere Spieler werden durch Bomben getötet. Spieler 1 spielt mit W,A,S,D und Leertaste und Spieler 2 spielt mit dem Pfeiltasten und Enter.
import arcade
import random
#Scaling of Tiles from Tilset and of Player
TILE_SCALING = 1
PLAYER_SCALING = 0.34
#Scaling of Sprites
NATIVE_SPRITE_SIZE = 32
SPRITE_SCALING = 1
SPRITE_SIZE = int(NATIVE_SPRITE_SIZE * SPRITE_SCALING)
#Scaling of the Bomb
BOMB_SCALING = 0.2
#Datas for cration of Window Class
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 800
SCREEN_TITLE = "BombIt"
GRID_PIXEL_SIZE = NATIVE_SPRITE_SIZE * TILE_SCALING
#The Speed with witch the Player moves
MOVEMENT_SPEED = 1
#For the Creation of the Maze -> Do not Change!!!!
TILE_EMPTY = 0
TILE_CRATE = 1
# Gridsize of the Maze
# Maze must have an ODD number of rows and columns.
# Walls go on EVEN rows/columns.
# Openings go on ODD rows/columns
MAZE_HEIGHT = 21
MAZE_WIDTH = 21
#Maze Sprite Technologie
MERGE_SPRITES = False
#Create Empty Grid for the Maze
def create_empty_grid(width, height, default_value=TILE_EMPTY):
""" Create an empty grid. """
grid = []
for row in range(height):
grid.append([])
for column in range(width):
grid[row].append(default_value)
return grid
#Create the Maze Structure
def make_maze_recursive_call(maze, top, bottom, left, right):
"""
Recursive function to divide up the maze in four sections
and create three gaps.
Walls can only go on even numbered rows/columns.
Gaps can only go on odd numbered rows/columns.
Maze must have an ODD number of rows and columns.
"""
# Figure out where to divide horizontally
start_range = bottom + 2
end_range = top - 1
y = random.randrange(start_range, end_range, 2)
# Do the division
for column in range(left + 1, right):
maze[y][column] = TILE_CRATE
# Figure out where to divide vertically
start_range = left + 2
end_range = right - 1
x = random.randrange(start_range, end_range, 2)
# Do the division
for row in range(bottom + 1, top):
maze[row][x] = TILE_CRATE
# Now we'll make a gap on 3 of the 4 walls.
# Figure out which wall does NOT get a gap.
wall = random.randrange(4)
if wall != 0:
gap = random.randrange(left + 1, x, 2)
maze[y][gap] = TILE_EMPTY
if wall != 1:
gap = random.randrange(x + 1, right, 2)
maze[y][gap] = TILE_EMPTY
if wall != 2:
gap = random.randrange(bottom + 1, y, 2)
maze[gap][x] = TILE_EMPTY
if wall != 3:
gap = random.randrange(y + 1, top, 2)
maze[gap][x] = TILE_EMPTY
# If there's enough space, to a recursive call.
if top > y + 3 and x > left + 3:
make_maze_recursive_call(maze, top, y, left, x)
if top > y + 3 and x + 3 < right:
make_maze_recursive_call(maze, top, y, x, right)
if bottom + 3 < y and x + 3 < right:
make_maze_recursive_call(maze, y, bottom, x, right)
if bottom + 3 < y and x > left + 3:
make_maze_recursive_call(maze, y, bottom, left, x)
#Create the Maze
def make_maze_recursion(maze_width, maze_height):
""" Make the maze by recursively splitting it into four rooms. """
maze = create_empty_grid(maze_width, maze_height)
# Start the recursive process
make_maze_recursive_call(maze, maze_height - 1, 0, 0, maze_width - 1)
return maze
#Class to Create the Player
class Player(arcade.Sprite):
def update(self):
""" Move the player """
# Move player.
# Remove these lines if physics engine is moving player.
self.center_x += self.change_x
self.center_y += self.change_y
# Check for out-of-bounds
if self.left < 0:
self.left = 0
elif self.right > SCREEN_WIDTH - 1:
self.right = SCREEN_WIDTH - 1
if self.bottom < 0:
self.bottom = 0
elif self.top > SCREEN_HEIGHT - 1:
self.top = SCREEN_HEIGHT - 1
# Klasse für die Bombe definieren
class Bomb(arcade.Sprite):
def __init__(self, x, y):
super().__init__(":resources:images/tiles/bomb.png", BOMB_SCALING)
self.center_x = x
self.center_y = y
# Timer für die Explosion starten
arcade.schedule(self.explode, 2)
self.explosion_sound = arcade.load_sound(':resources:sounds/explosion2.wav')
def explode(self, delta_time):
self.append_texture(arcade.load_texture('./map/tiles/explosion.png'))
self.set_texture(1)
arcade.sound.play_sound(self.explosion_sound)
arcade.unschedule(self.explode)
arcade.schedule(self.remove_bomb, 1)
#Bombe aus der Sprite-Liste entfernen
def remove_bomb(self, bomb):
self.remove_from_sprite_lists()
arcade.unschedule(self.remove_bomb)
class MyGame(arcade.Window):
def __init__(self):
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
self.tile_map = None
self.player_list = None
self.wall_list = None
self.ground_list = None
self.fence_list = None
self.wall_list = None
self.player_sprite = None
self.physics_engine = None
def setup(self):
self.player_list = arcade.SpriteList()
self.wall_list = arcade.SpriteList()
self.bomb_list = arcade.SpriteList()
self.exploded_list = arcade.SpriteList()
# Create the maze
maze = make_maze_recursion(MAZE_WIDTH, MAZE_HEIGHT)
# Create sprites based on 2D grid
if not MERGE_SPRITES:
# This is the simple-to-understand method. Each grid location
# is a sprite.
for row in range(MAZE_HEIGHT):
for column in range(MAZE_WIDTH):
if maze[row][column] == 1:
wall = arcade.Sprite("./map/tiles/rock_big.png", SPRITE_SCALING)
wall.center_x = (column * SPRITE_SIZE + SPRITE_SIZE / 2)+64
wall.center_y = (row * SPRITE_SIZE + SPRITE_SIZE / 2)+64
self.wall_list.append(wall)
else:
# This uses new Arcade 1.3.1 features, that allow me to create a
# larger sprite with a repeating texture. So if there are multiple
# cells in a row with a wall, we merge them into one sprite, with a
# repeating texture for each cell. This reduces our sprite count.
for row in range(MAZE_HEIGHT):
column = 0
while column < len(maze):
while column < len(maze) and maze[row][column] == 0:
column += 1
start_column = column
while column < len(maze) and maze[row][column] == 1:
column += 1
end_column = column - 1
column_count = end_column - start_column + 1
column_mid = (start_column + end_column) / 2
wall = arcade.Sprite("./map/tiles/rock_big.png", SPRITE_SCALING)
wall.center_x = (column_mid * SPRITE_SIZE + SPRITE_SIZE / 2)+64
wall.center_y = (row * SPRITE_SIZE + SPRITE_SIZE / 2)+64
wall.width = SPRITE_SIZE * column_count
self.wall_list.append(wall)
self.player_sprite = Player(
":resources:images/animated_characters/robot/robot_idle.png",
PLAYER_SCALING,
)
playerPosition = random.randrange(4)
if(playerPosition == 0):
self.player_sprite.center_x = 80
self.player_sprite.center_y = 80
elif(playerPosition == 1):
self.player_sprite.center_x = 800-80
self.player_sprite.center_y = 80
elif(playerPosition == 2):
self.player_sprite.center_x = 800-80
self.player_sprite.center_y = 800-80
elif(playerPosition == 3):
self.player_sprite.center_x = 80
self.player_sprite.center_y = 800-80
else:
self.player_sprite.center_x = 80
self.player_sprite.center_y = 80
self.player_list.append(self.player_sprite)
map_name = "map/map1.json"
layer_options = {
"Ground": {"use_spatial_hash": True},
"Fences": {"use_spatial_hash": True},
}
self.tile_map = arcade.load_tilemap(
'./map1.json', layer_options=layer_options, scaling=TILE_SCALING
)
self.end_of_map = self.tile_map.width * GRID_PIXEL_SIZE
self.ground_list = self.tile_map.sprite_lists["Ground"]
self.fence_list = self.tile_map.sprite_lists["Fences"]
if self.tile_map.background_color:
arcade.set_background_color(self.tile_map.background_color)
self.physics_engine = arcade.PhysicsEngineSimple(self.player_sprite, [self.fence_list, self.wall_list])
def on_draw(self):
self.clear()
self.ground_list.draw()
self.fence_list.draw()
self.player_list.draw()
self.wall_list.draw()
self.bomb_list.draw()
self.exploded_list.draw()
def on_key_press(self, key, modifiers):
if key == arcade.key.UP:
self.player_sprite.change_y = MOVEMENT_SPEED
elif key == arcade.key.DOWN:
self.player_sprite.change_y = -MOVEMENT_SPEED
elif key == arcade.key.LEFT:
self.player_sprite.change_x = -MOVEMENT_SPEED
elif key == arcade.key.RIGHT:
self.player_sprite.change_x = MOVEMENT_SPEED
# Bombe legen mit der Leertaste
elif key == arcade.key.SPACE:
bomb = Bomb((self.player_sprite.center_x//32)*32+16, (self.player_sprite.center_y//32)*32+16)
self.bomb_list.append(bomb)
def on_key_release(self, key, modifiers):
if key == arcade.key.UP or key == arcade.key.DOWN:
self.player_sprite.change_y = 0
elif key == arcade.key.LEFT or key == arcade.key.RIGHT:
self.player_sprite.change_x = 0
def on_update(self, delta_time):
self.player_list.update()
self.physics_engine.update()
def main():
window = MyGame()
window.setup()
arcade.run()
if __name__ == "__main__":
main()