I am developing a simple platformer game using the arcade game library of Python. I am still new to this, but I have tried to use as much object oriented programming as I could. I have successfully setup two "rooms" or levels of the game. However, I cannot figure out how to move to the second room after finishing the first room. Here is my code:
import arcade
import os
import random
SPRITE_SCALING = 0.5
SPRITE_SCALING_COIN = 0.3
SPRITE_NATIVE_SIZE = 128
SPRITE_SIZE = int(SPRITE_NATIVE_SIZE * SPRITE_SCALING)
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
SCREEN_TITLE = "Help Nick Adams!"
# Physics
MOVEMENT_SPEED = 5
JUMP_SPEED = 12
GRAVITY = 0.5
class Room:
# Class to hold info about rooms/levels
def __init__(self):
self.wall_list = self.goal_list = self.enemy_list = self.victory_sprite = None
self.collectedCoins = 0
self.numCoins = 0
def setup_room_1():
room = Room()
room.wall_list = arcade.SpriteList(use_spatial_hash=True)
room.enemy_list = arcade.SpriteList()
room.goal_list = arcade.SpriteList(use_spatial_hash=True)
room.victory_sprite = arcade.SpriteList(use_spatial_hash=True)
# Draw platforms and ground
for x in range(0, SCREEN_WIDTH, SPRITE_SIZE):
wall = arcade.Sprite(":resources:images/tiles/grassMid.png", SPRITE_SCALING)
wall.bottom = 0
wall.left = x
room.wall_list.append(wall)
for x in range(SPRITE_SIZE * 3, SPRITE_SIZE * 8, SPRITE_SIZE):
wall = arcade.Sprite(":resources:images/tiles/grassMid.png", SPRITE_SCALING)
wall.bottom = SPRITE_SIZE * 3
wall.left = x
room.wall_list.append(wall)
# Draw the crates
for x in range(0, SCREEN_WIDTH, SPRITE_SIZE * 5):
wall = arcade.Sprite(":resources:images/tiles/boxCrate_double.png", SPRITE_SCALING)
wall.bottom = SPRITE_SIZE
wall.left = x
room.wall_list.append(wall)
# Draw an enemy 1
enemy = arcade.Sprite(":resources:images/enemies/wormGreen.png", SPRITE_SCALING)
enemy.bottom = SPRITE_SIZE
enemy.left = SPRITE_SIZE * 2
enemy.change_x = 2
room.enemy_list.append(enemy)
# -- Draw enemy2 on the platform
enemy = arcade.Sprite(":resources:images/enemies/wormGreen.png", SPRITE_SCALING)
enemy.bottom = SPRITE_SIZE * 4
enemy.left = SPRITE_SIZE * 4
# Set boundaries for enemy
enemy.boundary_right = SPRITE_SIZE * 8
enemy.boundary_left = SPRITE_SIZE * 3
enemy.change_x = 2
room.enemy_list.append(enemy)
# Set up coins
for pos in [[128, 96], [418, 300], [670, 150]]:
goal = arcade.Sprite(":resources:images/items/coinGold.png", SPRITE_SCALING)
goal.center_x = pos[0]
goal.center_y = pos[1]
room.goal_list.append(goal)
room.numCoins += 1
# Set up checkpoint/level clear
flag = arcade.Sprite(":resources:images/tiles/signExit.png", SPRITE_SCALING)
flag.center_x = 770
flag.center_y = 96
room.victory_sprite.append(flag)
# Load the background image for this level.
room.background = arcade.load_texture(":resources:images/backgrounds/abstract_1.jpg")
return room
def setup_room_2():
room = Room()
room.wall_list = arcade.SpriteList(use_spatial_hash=True)
room.enemy_list = arcade.SpriteList()
room.goal_list = arcade.SpriteList(use_spatial_hash=True)
room.victory_sprite = arcade.SpriteList(use_spatial_hash=True)
# Set up walls
for y in range(0, 800, 200):
for x in range(100, 700, 64):
wall = arcade.Sprite(":resources:images/tiles/boxCrate_double.png", SPRITE_SCALING)
wall.center_x = x
wall.center_y = y
room.wall_list.append(wall)
for pos in [[35, 40], [765, 80], [35, 280], [765, 480]]:
wall = arcade.Sprite(":resources:images/tiles/grassHalf.png", SPRITE_SCALING)
wall.center_x = pos[0]
wall.center_y = pos[1]
room.wall_list.append(wall)
# Create the coins
for i in range(50):
# Create the coin instance
# Coin image from kenney.nl
goal = arcade.Sprite(":resources:images/items/coinGold.png", SPRITE_SCALING_COIN)
# Boolean variable if we successfully placed the coin
coin_placed_successfully = False
# Keep trying until success
while not coin_placed_successfully:
# Position the coin
goal.center_x = random.randrange(100, 700)
goal.center_y = random.randrange(SCREEN_HEIGHT)
# See if the coin is hitting a wall
wall_hit_list = arcade.check_for_collision_with_list(goal, room.wall_list)
# See if the coin is hitting another coin
coin_hit_list = arcade.check_for_collision_with_list(goal, room.goal_list)
if len(wall_hit_list) == 0 and len(coin_hit_list) == 0:
coin_placed_successfully = True
# Add the coin to the lists
room.goal_list.append(goal)
room.numCoins += 1
# Draw an enemy1
enemy = arcade.Sprite(":resources:images/enemies/fly.png", SPRITE_SCALING_COIN)
enemy.bottom = SPRITE_SIZE
enemy.left = SPRITE_SIZE * 2
enemy.boundary_right = SPRITE_SIZE * 8 + 60
enemy.boundary_left = SPRITE_SIZE * 1 + 60
enemy.change_x = 3
room.enemy_list.append(enemy)
# Draw a enemy2
enemy = arcade.Sprite(":resources:images/enemies/fly.png", SPRITE_SCALING_COIN)
enemy.bottom = SPRITE_SIZE * 4
enemy.left = SPRITE_SIZE * 4
enemy.boundary_right = SPRITE_SIZE * 8
enemy.boundary_left = SPRITE_SIZE * 3
enemy.change_x = 4
room.enemy_list.append(enemy)
# Draw a enemy3
enemy = arcade.Sprite(":resources:images/enemies/fly.png", SPRITE_SCALING_COIN)
enemy.bottom = SPRITE_SIZE * 7.2
enemy.left = SPRITE_SIZE * 4
enemy.boundary_right = SPRITE_SIZE * 8 + 80
enemy.boundary_left = SPRITE_SIZE * 3
enemy.change_x = 4.8
room.enemy_list.append(enemy)
# Draw victory point
flag = arcade.Sprite(":resources:images/tiles/signExit.png", SPRITE_SCALING)
flag.center_x = 765
flag.center_y = 545
room.victory_sprite.append(flag)
# Load the background image for this level.
room.background = arcade.load_texture(":resources:images/backgrounds/abstract_1.jpg")
return room
class MainGame(arcade.Window):
def __init__(self):
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
file_path = os.path.dirname(os.path.abspath(__file__))
os.chdir(file_path)
# Sprites and set up player
self.player_list = self.rooms = self.player_sprite = self.physics_engine = None
self.current_room = self.view_left = self.view_bottom = self.collectedCoins = 0
self.game_over = False
# Load sounds
self.collect_goal_sound = arcade.load_sound(":resources:sounds/coin1.wav")
self.jump_sound = arcade.load_sound(":resources:sounds/jump1.wav")
def setup(self):
""" Set up the game and initialize the variables. """
# -- Set up the player
self.player_sprite = arcade.Sprite(":resources:images/animated_characters/female_person/femalePerson_idle.png",
SPRITE_SCALING)
# list of rooms
self.rooms = []
# Create the rooms
room = setup_room_1()
self.rooms.append(room)
room = setup_room_2()
self.rooms.append(room)
# Starting room number
self.current_room = 0
# Player start position according to room number
if self.current_room == 0:
self.player_sprite.center_x = 64
self.player_sprite.center_y = 270
elif self.current_room == 1:
self.player_sprite.center_x = 35
self.player_sprite.center_y = 55
self.player_list = arcade.SpriteList()
self.player_list.append(self.player_sprite)
# Create a physics engine
self.physics_engine = arcade.PhysicsEnginePlatformer(self.player_sprite, self.rooms[self.current_room].wall_list
)
# Set the background color
arcade.set_background_color(arcade.color.AMAZON)
def on_draw(self):
arcade.start_render()
self.rooms[self.current_room].wall_list.draw()
self.rooms[self.current_room].goal_list.draw()
self.rooms[self.current_room].enemy_list.draw()
self.rooms[self.current_room].victory_sprite.draw()
# Draw all the sprites.
self.player_list.draw()
def on_key_press(self, key, modifiers):
if key == arcade.key.UP:
if self.physics_engine.can_jump():
self.player_sprite.change_y = JUMP_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
def on_key_release(self, key, modifiers):
if key == arcade.key.LEFT or key == arcade.key.RIGHT:
self.player_sprite.change_x = 0
def on_update(self, delta_time):
if not self.game_over:
# Move the enemies
self.rooms[self.current_room].enemy_list.update()
# Check each enemy
for enemy in self.rooms[self.current_room].enemy_list:
# If the enemy hit a wall, reverse
if len(arcade.check_for_collision_with_list(enemy, self.rooms[self.current_room].wall_list)) > 0:
enemy.change_x *= -1
# If the enemy hit the left boundary, reverse
elif enemy.boundary_left is not None and enemy.left < enemy.boundary_left:
enemy.change_x *= -1
# If the enemy hit the right boundary, reverse
elif enemy.boundary_right is not None and enemy.right > enemy.boundary_right:
enemy.change_x *= -1
# Update the player using the physics engine
self.physics_engine.update()
# See if we hit any coins
goal_hit_list = arcade.check_for_collision_with_list(self.player_sprite,
self.rooms[self.current_room].goal_list)
# Loop through each coin we hit (if any) and remove it
for goal in goal_hit_list:
# Remove the coin
goal.remove_from_sprite_lists()
# Play a sound
arcade.play_sound(self.collect_goal_sound)
# Count number of coins collected
self.collectedCoins += 1
if self.player_sprite.center_x <= -10 or self.player_sprite.center_x >= 800:
self.player_sprite.change_x = 0
self.player_sprite.change_y = 0
self.player_sprite.center_x = 64
self.player_sprite.center_y = 270
# See if the player hit a worm
if len(arcade.check_for_collision_with_list(self.player_sprite,
self.rooms[self.current_room].enemy_list)) > 0:
self.game_over = True
# See if the player hit the flag. If so, progress to round 2 ??????
if arcade.check_for_collision_with_list(self.player_sprite,
self.rooms[
self.current_room].victory_sprite) and self.collectedCoins == \
self.rooms[self.current_room].numCoins:
self.game_over = True
self.current_room += 1
def main():
window = MainGame()
window.setup()
arcade.run()
if __name__ == "__main__":
main()
If I delete self.gameover= True from the def update, the program transitions into room 2 but the sprites aren't loaded properly and player position is not reset.
replace self.game_over = True with self.setup()
Move creation of rooms from setup to __init__
Updated script:
import arcade
import os
import random
SPRITE_SCALING = 0.5
SPRITE_SCALING_COIN = 0.3
SPRITE_NATIVE_SIZE = 128
SPRITE_SIZE = int(SPRITE_NATIVE_SIZE * SPRITE_SCALING)
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
SCREEN_TITLE = "Help Nick Adams!"
# Physics
MOVEMENT_SPEED = 5
JUMP_SPEED = 12
GRAVITY = 0.5
class Room:
# Class to hold info about rooms/levels
def __init__(self):
self.wall_list = self.goal_list = self.enemy_list = self.victory_sprite = None
self.collectedCoins = 0
self.numCoins = 0
def setup_room_1():
room = Room()
room.wall_list = arcade.SpriteList(use_spatial_hash=True)
room.enemy_list = arcade.SpriteList()
room.goal_list = arcade.SpriteList(use_spatial_hash=True)
room.victory_sprite = arcade.SpriteList(use_spatial_hash=True)
# Draw platforms and ground
for x in range(0, SCREEN_WIDTH, SPRITE_SIZE):
wall = arcade.Sprite(":resources:images/tiles/grassMid.png", SPRITE_SCALING)
wall.bottom = 0
wall.left = x
room.wall_list.append(wall)
for x in range(SPRITE_SIZE * 3, SPRITE_SIZE * 8, SPRITE_SIZE):
wall = arcade.Sprite(":resources:images/tiles/grassMid.png", SPRITE_SCALING)
wall.bottom = SPRITE_SIZE * 3
wall.left = x
room.wall_list.append(wall)
# Draw the crates
for x in range(0, SCREEN_WIDTH, SPRITE_SIZE * 5):
wall = arcade.Sprite(":resources:images/tiles/boxCrate_double.png", SPRITE_SCALING)
wall.bottom = SPRITE_SIZE
wall.left = x
room.wall_list.append(wall)
# Draw an enemy 1
enemy = arcade.Sprite(":resources:images/enemies/wormGreen.png", SPRITE_SCALING)
enemy.bottom = SPRITE_SIZE
enemy.left = SPRITE_SIZE * 2
enemy.change_x = 2
room.enemy_list.append(enemy)
# -- Draw enemy2 on the platform
enemy = arcade.Sprite(":resources:images/enemies/wormGreen.png", SPRITE_SCALING)
enemy.bottom = SPRITE_SIZE * 4
enemy.left = SPRITE_SIZE * 4
# Set boundaries for enemy
enemy.boundary_right = SPRITE_SIZE * 8
enemy.boundary_left = SPRITE_SIZE * 3
enemy.change_x = 2
room.enemy_list.append(enemy)
# Set up coins
for pos in [[128, 96], [418, 300], [670, 150]]:
goal = arcade.Sprite(":resources:images/items/coinGold.png", SPRITE_SCALING)
goal.center_x = pos[0]
goal.center_y = pos[1]
room.goal_list.append(goal)
room.numCoins += 1
# Set up checkpoint/level clear
flag = arcade.Sprite(":resources:images/tiles/signExit.png", SPRITE_SCALING)
flag.center_x = 770
flag.center_y = 96
room.victory_sprite.append(flag)
# Load the background image for this level.
room.background = arcade.load_texture(":resources:images/backgrounds/abstract_1.jpg")
return room
def setup_room_2():
room = Room()
room.wall_list = arcade.SpriteList(use_spatial_hash=True)
room.enemy_list = arcade.SpriteList()
room.goal_list = arcade.SpriteList(use_spatial_hash=True)
room.victory_sprite = arcade.SpriteList(use_spatial_hash=True)
# Set up walls
for y in range(0, 800, 200):
for x in range(100, 700, 64):
wall = arcade.Sprite(":resources:images/tiles/boxCrate_double.png", SPRITE_SCALING)
wall.center_x = x
wall.center_y = y
room.wall_list.append(wall)
for pos in [[35, 40], [765, 80], [35, 280], [765, 480]]:
wall = arcade.Sprite(":resources:images/tiles/grassHalf.png", SPRITE_SCALING)
wall.center_x = pos[0]
wall.center_y = pos[1]
room.wall_list.append(wall)
# Create the coins
for i in range(50):
# Create the coin instance
# Coin image from kenney.nl
goal = arcade.Sprite(":resources:images/items/coinGold.png", SPRITE_SCALING_COIN)
# Boolean variable if we successfully placed the coin
coin_placed_successfully = False
# Keep trying until success
while not coin_placed_successfully:
# Position the coin
goal.center_x = random.randrange(100, 700)
goal.center_y = random.randrange(SCREEN_HEIGHT)
# See if the coin is hitting a wall
wall_hit_list = arcade.check_for_collision_with_list(goal, room.wall_list)
# See if the coin is hitting another coin
coin_hit_list = arcade.check_for_collision_with_list(goal, room.goal_list)
if len(wall_hit_list) == 0 and len(coin_hit_list) == 0:
coin_placed_successfully = True
# Add the coin to the lists
room.goal_list.append(goal)
room.numCoins += 1
# Draw an enemy1
enemy = arcade.Sprite(":resources:images/enemies/fly.png", SPRITE_SCALING_COIN)
enemy.bottom = SPRITE_SIZE
enemy.left = SPRITE_SIZE * 2
enemy.boundary_right = SPRITE_SIZE * 8 + 60
enemy.boundary_left = SPRITE_SIZE * 1 + 60
enemy.change_x = 3
room.enemy_list.append(enemy)
# Draw a enemy2
enemy = arcade.Sprite(":resources:images/enemies/fly.png", SPRITE_SCALING_COIN)
enemy.bottom = SPRITE_SIZE * 4
enemy.left = SPRITE_SIZE * 4
enemy.boundary_right = SPRITE_SIZE * 8
enemy.boundary_left = SPRITE_SIZE * 3
enemy.change_x = 4
room.enemy_list.append(enemy)
# Draw a enemy3
enemy = arcade.Sprite(":resources:images/enemies/fly.png", SPRITE_SCALING_COIN)
enemy.bottom = SPRITE_SIZE * 7.2
enemy.left = SPRITE_SIZE * 4
enemy.boundary_right = SPRITE_SIZE * 8 + 80
enemy.boundary_left = SPRITE_SIZE * 3
enemy.change_x = 4.8
room.enemy_list.append(enemy)
# Draw victory point
flag = arcade.Sprite(":resources:images/tiles/signExit.png", SPRITE_SCALING)
flag.center_x = 765
flag.center_y = 545
room.victory_sprite.append(flag)
# Load the background image for this level.
room.background = arcade.load_texture(":resources:images/backgrounds/abstract_1.jpg")
return room
class MainGame(arcade.Window):
def __init__(self):
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
file_path = os.path.dirname(os.path.abspath(__file__))
os.chdir(file_path)
# Sprites and set up player
self.player_list = self.rooms = self.player_sprite = self.physics_engine = None
self.current_room = self.view_left = self.view_bottom = self.collectedCoins = 0
self.game_over = False
# Load sounds
self.collect_goal_sound = arcade.load_sound(":resources:sounds/coin1.wav")
self.jump_sound = arcade.load_sound(":resources:sounds/jump1.wav")
# Starting room number
self.current_room = 0
# list of rooms
self.rooms = []
# Create the rooms
room = setup_room_1()
self.rooms.append(room)
room = setup_room_2()
self.rooms.append(room)
def setup(self):
""" Set up the game and initialize the variables. """
# -- Set up the player
self.player_sprite = arcade.Sprite(":resources:images/animated_characters/female_person/femalePerson_idle.png", SPRITE_SCALING)
# Player start position according to room number
if self.current_room == 0:
self.player_sprite.center_x = 64
self.player_sprite.center_y = 270
elif self.current_room == 1:
self.player_sprite.center_x = 35
self.player_sprite.center_y = 55
self.player_list = arcade.SpriteList()
self.player_list.append(self.player_sprite)
# Create a physics engine
self.physics_engine = arcade.PhysicsEnginePlatformer(self.player_sprite, self.rooms[self.current_room].wall_list)
# Set the background color
arcade.set_background_color(arcade.color.AMAZON)
def on_draw(self):
arcade.start_render()
self.rooms[self.current_room].wall_list.draw()
self.rooms[self.current_room].goal_list.draw()
self.rooms[self.current_room].enemy_list.draw()
self.rooms[self.current_room].victory_sprite.draw()
# Draw all the sprites.
self.player_list.draw()
def on_key_press(self, key, modifiers):
if key == arcade.key.UP:
if self.physics_engine.can_jump():
self.player_sprite.change_y = JUMP_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
def on_key_release(self, key, modifiers):
if key == arcade.key.LEFT or key == arcade.key.RIGHT:
self.player_sprite.change_x = 0
def on_update(self, delta_time):
if not self.game_over:
# Move the enemies
self.rooms[self.current_room].enemy_list.update()
# Check each enemy
for enemy in self.rooms[self.current_room].enemy_list:
# If the enemy hit a wall, reverse
if len(arcade.check_for_collision_with_list(enemy, self.rooms[self.current_room].wall_list)) > 0:
enemy.change_x *= -1
# If the enemy hit the left boundary, reverse
elif enemy.boundary_left is not None and enemy.left < enemy.boundary_left:
enemy.change_x *= -1
# If the enemy hit the right boundary, reverse
elif enemy.boundary_right is not None and enemy.right > enemy.boundary_right:
enemy.change_x *= -1
# Update the player using the physics engine
self.physics_engine.update()
# See if we hit any coins
goal_hit_list = arcade.check_for_collision_with_list(self.player_sprite, self.rooms[self.current_room].goal_list)
# Loop through each coin we hit (if any) and remove it
for goal in goal_hit_list:
# Remove the coin
goal.remove_from_sprite_lists()
# Play a sound
arcade.play_sound(self.collect_goal_sound)
# Count number of coins collected
self.collectedCoins += 1
if self.player_sprite.center_x <= -10 or self.player_sprite.center_x >= 800:
self.player_sprite.change_x = 0
self.player_sprite.change_y = 0
self.player_sprite.center_x = 64
self.player_sprite.center_y = 270
# See if the player hit a worm
if len(arcade.check_for_collision_with_list(self.player_sprite, self.rooms[self.current_room].enemy_list)) > 0:
self.game_over = True
# See if the player hit the flag. If so, progress to round 2 ??????
if arcade.check_for_collision_with_list(self.player_sprite, self.rooms[self.current_room].victory_sprite) and self.collectedCoins == self.rooms[self.current_room].numCoins:
# self.game_over = True
self.current_room += 1
self.setup()
def main():
window = MainGame()
window.setup()
arcade.run()
if __name__ == "__main__":
main()
Related
I am getting this error when trying to run my code, the error.
Traceback (most recent call last):
File "D:/Colin Lewis/pythonProject3/Lib/import_tileset.py", line 264, in <module>
main()
File "D:/Colin Lewis/pythonProject3/Lib/import_tileset.py", line 259, in main
window.setup()
File "D:/Colin Lewis/pythonProject3/Lib/import_tileset.py", line 181, in setup
self.scene.add_sprite(LAYER_NAME_PLAYER, self.player_sprite)
File "D:\Colin Lewis\pythonProject3\lib\site-packages\arcade\scene.py", line 95, in add_sprite
new_list.append(sprite)
File "D:\Colin Lewis\pythonProject3\lib\site-packages\arcade\sprite_list\sprite_list.py", line 625, in append
self._atlas.add(texture)
File "D:\Colin Lewis\pythonProject3\lib\site-packages\arcade\texture_atlas.py", line 284, in add
if self.has_texture(texture):
File "D:\Colin Lewis\pythonProject3\lib\site-packages\arcade\texture_atlas.py", line 452, in has_texture
return texture.name in self._atlas_regions
AttributeError: 'str' object has no attribute 'name'
If anyone knows how to solve this, please help me.
here is my code:
# Colin A. Lewis
# Path of Torment
# Friday, April 1st 2022
# Coding, App & Game Design - A.M.
import os
import arcade
# Constants
SCREEN_WIDTH = 1900
SCREEN_HEIGHT = 1200
SCREEN_TITLE = "Forest_of_Acid_&_Spikes"
# Constants used to scale our sprites from their original size
TILE_SCALING = 0.75
CHARACTER_SCALING = TILE_SCALING * 2
SPRITE_PIXEL_SIZE = 64
GRID_PIXEL_SIZE = SPRITE_PIXEL_SIZE * TILE_SCALING
# How many pixels to keep as a minimum margin between the character
# and the edge of the screen.
LEFT_VIEWPORT_MARGIN = 200
RIGHT_VIEWPORT_MARGIN = 200
BOTTOM_VIEWPORT_MARGIN = 150
TOP_VIEWPORT_MARGIN = 100
# Movement speed of player, in pixels per frame
PLAYER_MOVEMENT_SPEED = 3
GRAVITY = 1.5
PLAYER_JUMP_SPEED = 30
PLAYER_START_X = 1
PLAYER_START_Y = 30
# Constants used to track if the player is facing left or right
RIGHT_FACING = 1
LEFT_FACING = 0
LAYER_NAME_TERRAIN = "Terrain"
LAYER_NAME_HAZARDS = "hazards"
LAYER_NAME_PLAYER = "player"
def load_frame(filename):
return [
arcade.load_texture(filename),
arcade.load_texture(filename, flipped_horizontally=True),
]
class Entity(arcade.Sprite):
def __init__(self):
super().__init__()
self.facing_direction = RIGHT_FACING
self.currentTexture = 0
self.scale = CHARACTER_SCALING
character = f"./Character/Run (1).png"
self.runFrames = []
for i in range(1, 8):
textures = f"{character}/Character/Run (1){i}.png"
self.runFrames.append(textures)
self.textures = self.runFrames[0][0]
class PlayerCharacter(Entity):
def __init__(self):
super().__init__()
def updateAnimation(self, delta_time: float = 1 / 8):
if self.change_x < 0 and self.facing_direction == RIGHT_FACING:
self.facing_direction = LEFT_FACING
elif self.change_x < 0 and self.facing_direction == LEFT_FACING:
self.facing_direction = RIGHT_FACING
# player run animation
if self.change_x != 0:
self.currentTexture += 1
if self.currentTexture > len(self.runFrames) - 1:
self.currentTexture = 0
self.currentTexture = self.runFrames[self.currentTexture][self.facing_direction]
class MyGame(arcade.Window):
def __init__(self):
# Calls from the parent class and sets up the main window
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
self.left_pressed = False
self.right_pressed = False
self.jump_needs_reset = False
self.up_pressed = False
self.down_pressed = False
# Set the path to start with this program
# File assertion
file_path = os.path.dirname(
os.path.abspath("D:\Colin Lewis\pythonProject3\Lib"))
os.chdir(file_path)
# Our TileMap Object
self.tile_map = ""
# Our Scene Object
self.scene = None
# Separate variable that holds the player sprite
self.player_sprite = None
# Our 'physics' engine
self.physics_engine = None
# A Camera that can be used for scrolling the screen
self.camera = None
# A Camera that can be used to draw GUI elements
self.gui_camera = None
self.end_of_map = 0
path = r"D:\\Colin Lewis\\pythonProject3\\Lib\\Forest_of_Acid_&_Spikes.tmx"
assert os.path.isfile(path)
with open(path, "r") as r:
pass
def setup(self):
"""Set up the game here. Call this function to restart the game."""
# Setup the Cameras
self.camera = arcade.Camera(self.width, self.height)
self.gui_camera = arcade.Camera(self.width, self.height)
# Map name
map_name = "D:\\Colin Lewis\\pythonProject3\\Lib\\Forest_of_Acid_&_Spikes.tmx"
# Layer Specific Options for the Tilemap
layer_options = {
LAYER_NAME_TERRAIN: {
"use_spatial_hash": True,
},
LAYER_NAME_HAZARDS: {
"use_spatial_hash": True,
},
LAYER_NAME_PLAYER: {
"use_spacial_hash": True
},
}
# Load in TileMap
print("Loading Tile Map")
print(map_name)
self.tile_map = arcade.load_tilemap(map_name, TILE_SCALING, layer_options)
print("Done loading Tile Map")
self.scene = arcade.Scene.from_tilemap(self.tile_map)
self.end_of_map = self.tile_map.width * GRID_PIXEL_SIZE
self.player_sprite = PlayerCharacter()
self.player_sprite.center_x = (
self.tile_map.tile_width * TILE_SCALING * PLAYER_START_X)
self.player_sprite.center_y = (
self.tile_map.tile_height * TILE_SCALING * PLAYER_START_Y
)
self.scene.add_sprite(LAYER_NAME_PLAYER, self.player_sprite)
self.end_of_map = self.tile_map.width * GRID_PIXEL_SIZE
# Create the 'physics engine'
self.physics_engine = arcade.PhysicsEnginePlatformer(
self.player_sprite,
gravity_constant=GRAVITY,
walls=(self.scene[LAYER_NAME_TERRAIN]))
def on_draw(self):
"""Render the screen."""
# Clear the screen to the background color
self.clear()
# Activate the game camera
self.camera.use()
# Draw our Scene
self.scene.draw()
# Activate the GUI camera before drawing GUI elements
self.gui_camera.use()
def process_keychange(self):
# Process left/right
if self.right_pressed and not self.left_pressed:
self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED
elif self.left_pressed and not self.right_pressed:
self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED
else:
self.player_sprite.change_x = 0
def on_key_press(self, key, modifiers):
if key == arcade.key.LEFT:
self.left_pressed = True
elif key == arcade.key.RIGHT:
self.right_pressed = True
self.process_keychange()
def on_key_release(self, key, modifiers):
if key == arcade.key.LEFT:
self.left_pressed = False
elif key == arcade.key.RIGHT:
self.right_pressed = False
self.process_keychange()
def center_camera_to_player(self, speed=0.2):
screen_center_x = self.player_sprite.center_x - (self.camera.viewport_width / 2)
screen_center_y = self.player_sprite.center_y - (
self.camera.viewport_height / 2
)
if screen_center_x < 0:
screen_center_x = 0
if screen_center_y < 0:
screen_center_y = 0
player_centered = screen_center_x, screen_center_y
self.camera.move_to(player_centered, speed)
# Draw hit boxes.
for wall in self.wall_list:
wall.draw_hit_box(arcade.color.BLACK, 3)
self.player_sprite.draw_hit_box(arcade.color.RED, 3)
def main():
"""Main function"""
window = MyGame()
window.setup()
arcade.run()
if __name__ == "__main__":
main()
This is where I think the error is coming from in the code:
print("Loading Tile Map")
print(map_name)
self.tile_map = arcade.load_tilemap(map_name, TILE_SCALING, layer_options)
print("Done loading Tile Map")
self.scene = arcade.Scene.from_tilemap(self.tile_map)
self.end_of_map = self.tile_map.width * GRID_PIXEL_SIZE
self.player_sprite = PlayerCharacter()
self.player_sprite.center_x = (
self.tile_map.tile_width * TILE_SCALING * PLAYER_START_X)
self.player_sprite.center_y = (
self.tile_map.tile_height * TILE_SCALING * PLAYER_START_Y
)
self.scene.add_sprite(LAYER_NAME_PLAYER, self.player_sprite)
self.end_of_map = self.tile_map.width * GRID_PIXEL_SIZE
# Create the 'physics engine'
self.physics_engine = arcade.PhysicsEnginePlatformer(
self.player_sprite,
gravity_constant=GRAVITY,
walls=(self.scene[LAYER_NAME_TERRAIN]))
def on_draw(self):
"""Render the screen."""
# Clear the screen to the background color
self.clear()
# Activate the game camera
self.camera.use()
# Draw our Scene
self.scene.draw()
# Activate the GUI camera before drawing GUI elements
self.gui_camera.use()
I'm making a game with pygame and pymunk as a physics engine. I'm trying to kill a bullet whenever it hits a player or goes past its lifetime.
When I tried to space.remove(self.shape) and the second bullet hits the player, it gives me an "AssertionError: shape not in space, already removed. I simply changed it to teleport the bullets away, and then learned of the real error.
When I have more than one bullet in the space and a bullet hits the enemy player, all the current bullets teleport away, which means that when I tried to remove one bullet, it called the remove on all the bullets and thats why I had the initial error.
However the problem still remains that one bullet is being treated as every bullet.
Why is something that should be a non-static variable being called as a static variable?
I even tried to use deepcopy to see if that fixed it, but to no avail
This is my chunk of code, apologies since I don't know what is needed to understand it.
The key parts are most likely the Bullet class, the shoot() function in the Player class, and the drawBulletCollision() function
# PyGame template.
# Import modules.
import sys, random, math, time, copy
from typing import List
import pygame
from pygame.locals import *
from pygame import mixer
import pymunk
import pymunk.pygame_util
from pymunk.shapes import Segment
from pymunk.vec2d import Vec2d
pygame.mixer.pre_init(44110, -16, 2, 512)
mixer.init()
# Set up the window.
width, height = 1440, 640
screen = pygame.display.set_mode((width, height))
bg = pygame.image.load("space.png")
def draw_bg():
screen.blit(bg, (0, 0))
#load sounds
#death_fx = pygame.mixer.Sound("")
#death_fx.set_volume(0.25)
shoot_fx = mixer.Sound("shot.wav")
shoot_fx.set_volume(0.25)
#mixer.music.load("video.mp3")
#mixer.music.play()
#time.sleep(2)
#mixer.music.stop()
#gun_mode_fx = pygame.mixer.Sound("")
#gun_mode_fx.set_volume(0.25)
#thrust_mode_fx = pygame.mixer.Sound("")
#thrust_mode_fx.set_volume(0.25)
collision_fx = mixer.Sound("thump.wav")
collision_fx.set_volume(0.25)
ship_group = pygame.sprite.Group()
space = pymunk.Space()
space.gravity = 0, 0
space.damping = 0.6
draw_options = pymunk.pygame_util.DrawOptions(screen)
bulletList = []
playerList = []
environmentList = []
arbiterList = []
b0 = space.static_body
segmentBot = pymunk.Segment(b0, (0,height), (width, height), 4)
segmentTop = pymunk.Segment(b0, (0,0), (width, 0), 4)
segmentLef = pymunk.Segment(b0, (width,0), (width, height), 4)
segmentRit = pymunk.Segment(b0, (0,0), (0, height), 4)
walls = [segmentBot,segmentLef,segmentRit,segmentTop]
for i in walls:
i.elasticity = 1
i.friction = 0.5
i.color = (255,255,255,255)
environmentList.append(i)
class Player(object):
radius = 30
def __init__(self, position, space, color):
self.body = pymunk.Body(mass=5,moment=10)
self.mode = 0 # 0 is gun, 1 is thrust, ? 2 is shield
self.body.position = position
self.shape = pymunk.Circle(self.body, radius = self.radius)
#self.image
#self.shape.friction = 0.9
self.shape.elasticity= 0.2
space.add(self.body,self.shape)
self.angleGun = 0
self.angleThrust = 0
self.health = 100
self.speed = 500
self.gearAngle = 0
self.turningSpeed = 5
self.shape.body.damping = 1000
self.cooldown = 0
self.fireRate = 30
self.shape.collision_type = 1
self.shape.color = color
playerList.append(self)
def force(self,force):
self.shape.body.apply_force_at_local_point(force,(0,0))
def rocketForce(self):
radians = self.angleThrust * math.pi/180
self.shape.body.apply_force_at_local_point((-self.speed * math.cos(radians),-self.speed * math.sin(radians)),(0,0))
def draw(self):
gear = pygame.image.load("gear.png")
gearBox = gear.get_rect(center=self.shape.body.position)
gearRotated = pygame.transform.rotate(gear, self.gearAngle)
#gearRotated.rect.center=self.shape.body.position
x,y = self.shape.body.position
radianGun = self.angleGun * math.pi/180
radianThrust = self.angleThrust * math.pi/180
radiyus = 30 *(100-self.health)/100
screen.blit(gearRotated,gearBox)
self.gearAngle += 1
if radiyus == 30:
radiyus = 32
pygame.draw.circle(screen,self.shape.color,self.shape.body.position,radiyus,0)
pygame.draw.circle(screen,(0,0,0),self.shape.body.position,radiyus,0)
pygame.draw.line(
screen,(0,255,0),
(self.radius * math.cos(radianGun) * 1.5 + x,self.radius * math.sin(radianGun) * 1.5 + y),
(x,y), 5
)
pygame.draw.line(
screen,(200,200,0),
(self.radius * math.cos(radianThrust) * 1.5 + x,self.radius * math.sin(radianThrust) * 1.5 + y),
(x,y), 5
)
#more
def targetAngleGun(self,tAngle):
tempTAngle = tAngle - self.angleGun
tempTAngle = tempTAngle % 360
if(tempTAngle < 180 and not tempTAngle == 0):
self.angleGun -= self.turningSpeed
elif(tempTAngle >= 180 and not tempTAngle == 0):
self.angleGun += self.turningSpeed
self.angleGun = self.angleGun % 360
#print(tAngle, "target Angle")
#print(self.angleGun, "selfangleGun")
#print(tempTAngle, "tempTAngle")
def targetAngleThrust(self,tAngle):
tempTAngle = tAngle - self.angleThrust
tempTAngle = tempTAngle % 360
if(tempTAngle < 180 and not tempTAngle == 0):
self.angleThrust -= self.turningSpeed
elif(tempTAngle >= 180 and not tempTAngle == 0):
self.angleThrust += self.turningSpeed
self.angleThrust = self.angleThrust % 360
#print(tAngle, "target Angle")
#print(self.angleThrust, "selfangleGun")
#print(tempTAngle, "tempTAngle")
def targetAngle(self,tAngle):
if(self.mode == 0):
self.targetAngleGun(tAngle)
elif(self.mode == 1):
self.targetAngleThrust(tAngle)
def shoot(self):
if(self.cooldown == self.fireRate):
x,y = self.shape.body.position
radianGun = self.angleGun * math.pi/180
spawnSpot = (self.radius * math.cos(radianGun) * 1.5 + x,self.radius * math.sin(radianGun)*1.5+y)
self.shape.body.apply_impulse_at_local_point((-20 * math.cos(radianGun),-20 * math.sin(radianGun)),(0,0))
print(spawnSpot)
bT = Bullet(spawnSpot, 5, 50,self.shape.color)
b = copy.deepcopy(bT)
bulletList.append(b)
space.add(b.shape,b.shape.body)
b.getShot(self.angleGun)
self.cooldown = 0
print('pew')
shoot_fx.play()
# HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEREEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
def tick(self):
self.draw()
if(self.cooldown < self.fireRate):
self.cooldown += 1
#for o in playerList:
# c = self.shape.shapes_collide(o.shape)
# if(len(c.points)>0):
# self.damage(c.points[0].distance/10)
for o in bulletList:
c = self.shape.shapes_collide(o.shape)
#print(c)
for o in walls:
c = self.shape.shapes_collide(o)
if(len(c.points)>0):
self.damage(c.points[0].distance * 3)
def damage(self, damage):
self.health -= abs(damage)
if self.health < 0:
self.health = 0
#maybe make it part of the player class
def drawWallCollision(arbiter, space, data):
for c in arbiter.contact_point_set.points:
r = max(3, abs(c.distance * 5))
r = int(r)
p = tuple(map(int, c.point_a))
pygame.draw.circle(data["surface"], pygame.Color("red"), p, r, 0)
print('magnitude', math.sqrt(arbiter.total_impulse[0]**2 + arbiter.total_impulse[1]**2))
#print('position', p)
#print(data)
print("its all arbitrary")
s1, s2 = arbiter.shapes
collision_fx.play()
def drawBulletCollision(arbiter, space, data):
s1, s2 = arbiter.shapes
for c in arbiter.contact_point_set.points:
magnitude = math.sqrt(arbiter.total_impulse[0]**2 + arbiter.total_impulse[1]**2)
for p in playerList:
avr = ((c.point_a[0] + c.point_b[0])/2, (c.point_a[1] + c.point_b[1])/2)
distance = (math.sqrt((avr[0] - p.shape.body.position[0]) **2 + (avr[1] - p.shape.body.position[1]) **2 ))
if(distance < Bullet.explosionRadius + Player.radius):
if not(s1.color == s2.color):
p.damage(magnitude)
for b in bulletList:
avr = ((c.point_a[0] + c.point_b[0])/2, (c.point_a[1] + c.point_b[1])/2)
distance = (math.sqrt((avr[0] - p.shape.body.position[0]) **2 + (avr[1] - p.shape.body.position[1]) **2 ))
if(distance < Bullet.explosionRadius + Player.radius):
if not(s1.color == s2.color):
b.damage(magnitude)
pygame.draw.circle(data["surface"], pygame.Color("red"), tuple(map(int, c.point_a)), 10, 0)
print('magnitude', magnitude)
#print('position', p)
#print(data)
print("its all arbitrary")
def drawArbitraryCollision(arbiter, space, data):
collision_fx.play()
class Ship(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("gear.png")
self.rect = self.image.get_rect()
self.rect.center = [x, y]
def rotate(self):
self.image = pygame.transform.rotate(self.image,1)
class Bullet(object):
damage = 2
explosionRadius = 5
def __init__(self, position, size, speed,color):
pts = [(-size, -size), (size, -size), (size, size), (-size, size)]
self.body = copy.deepcopy(pymunk.Body(mass=0.1,moment=1))
self.shape = copy.deepcopy(pymunk.Poly(self.body, pts))
self.shape.body.position = position
self.shape.friction = 0.5
self.shape.elasticity = 1
self.shape.color = color
self.speed = speed
self.size = size
self.shape.collision_type = 2
#space.add(self.body,self.shape)
#bulletList.append(self)
self.lifetime = 0
def getShot(self,angle):
radians = angle * math.pi/180
self.shape.body.apply_impulse_at_local_point((self.speed * math.cos(radians),self.speed * math.sin(radians)),(0,0))
def tick(self):
self.lifetime += 1
if(self.lifetime > 300):
self.shape.body.position = (10000,30)
def damage(self, damage):
self.lifetime = 300
#VELOCITY OF BULLET STARTS WITH VELOCITY OF PLAYER
#MAKE VOLUME OF SOUND DEPEND ON THE IMPULSE FOR THE IMPACTS
#error on purpose so you notice this
#INSTANCES NOT WORKING????
def runPyGame():
# Initialise PyGame.
pygame.init()
# Set up the clock. This will tick every frame and thus maintain a relatively constant framerate. Hopefully.
fps = 60.0
fpsClock = pygame.time.Clock()
running = True
font = pygame.font.SysFont("Arial", 16)
p1 = Player((240,240),space,(132, 66, 245,255))
p2 = Player((1200,400),space,(47, 247, 184,255))
space.add(segmentBot,segmentTop,segmentLef,segmentRit)
# Main game loop.
ch = space.add_collision_handler(1, 0)
ch.data["surface"] = screen
ch.post_solve = drawWallCollision
ch = space.add_collision_handler(1, 2)
ch.data["surface"] = screen
ch.post_solve = drawBulletCollision
ch = space.add_collision_handler(0, 2)
ch.data["surface"] = screen
ch.post_solve = drawArbitraryCollision
dt = 1/fps # dt is the time since last frame.
while True: # Loop forever!
keys = pygame.key.get_pressed()
for event in pygame.event.get():
# We need to handle these events. Initially the only one you'll want to care
# about is the QUIT event, because if you don't handle it, your game will crash
# whenever someone tries to exit.
if event.type == QUIT:
pygame.quit() # Opposite of pygame.init
sys.exit() # Not including this line crashes the script on Windows.
if event.type == KEYDOWN:
if event.key == pygame.K_s:
p1.mode = -(p1.mode - 0.5) + 0.5
print(p1.mode)
if (event.key == pygame.K_k and p1.mode == 0):
p1.shoot()
if event.key == pygame.K_KP_5:
p2.mode = -(p2.mode - 0.5) + 0.5
print(p2.mode)
if (event.key == pygame.K_m and p2.mode == 0):
p2.shoot()
#b = Bullet((200,200),51,51)
if(keys[K_w]):
p1.targetAngle(90)
if(keys[K_q]):
p1.targetAngle(45)
if(keys[K_a]):
p1.targetAngle(0)
if(keys[K_z]):
p1.targetAngle(315)
if(keys[K_x]):
p1.targetAngle(270)
if(keys[K_c]):
p1.targetAngle(225)
if(keys[K_d]):
p1.targetAngle(180)
if(keys[K_e]):
p1.targetAngle(135)
if(keys[K_k] and p1.mode == 1):
p1.rocketForce()
if(keys[K_KP_8]):
p2.targetAngle(90)
if(keys[K_KP_7]):
p2.targetAngle(45)
if(keys[K_KP_4]):
p2.targetAngle(0)
if(keys[K_KP_1]):
p2.targetAngle(315)
if(keys[K_KP_2]):
p2.targetAngle(270)
if(keys[K_KP_3]):
p2.targetAngle(225)
if(keys[K_KP_6]):
p2.targetAngle(180)
if(keys[K_KP_9]):
p2.targetAngle(135)
if(keys[K_m] and p2.mode == 1):
p2.rocketForce()
# Handle other events as you wish.
screen.fill((250, 250, 250)) # Fill the screen with black.
# Redraw screen here.
### Draw stuff
draw_bg()
space.debug_draw(draw_options)
for i in playerList:
i.tick()
screen.blit(
font.render("P1 Health: " + str(p1.health), True, pygame.Color("white")),
(50, 10),
)
screen.blit(
font.render("P2 Health: " + str(p2.health), True, pygame.Color("white")),
(50, 30),
)
for i in bulletList:
i.tick()
ship_group.draw(screen)
# Flip the display so that the things we drew actually show up.
pygame.display.update()
dt = fpsClock.tick(fps)
space.step(0.01)
pygame.display.update()
runPyGame()
I cant point to the exact error since the code is quite long and depends on files I dont have. But here is a general advice for troubleshooting:
Try to give a name to each shape when you create them, and then print it out. Also print out the name of each shape that you add or remove from the space. This should show which shape you are actually removing and will probably make it easy to understand whats wrong.
For example:
...
self.shape = pymunk.Circle(self.body, radius = self.radius)
self.shape.name = "circle 1"
print("Created", self.shape.name)
...
print("Adding", self.shape.name)
space.add(self.body,self.shape)
...
(Note that you need to reset the name of shapes you copy, since otherwise the copy will have the same name.)
I have created snake game in python and am using NEAT to create an Neural network to play the game. I have put a lot of time into playing around with the config file and fitness functions but the average fitness doesn't increase. I would really love if someone could give some advice.
I have attached the python file for the game and also the NEAT config file I used and commented the code for readability.
import os
import random
import pygame
import neat
from scipy.spatial import distance
gen = 0
snakes = []
snacks = []
rows = 20
def draw_grid(w, surface):
size_btwn = w // rows
x, y = 0, 0
for l in range(rows):
x = x + size_btwn
y = y + size_btwn
pygame.draw.line(surface, (255, 255, 255), (x, 0), (x, w))
pygame.draw.line(surface, (255, 255, 255), (0, y), (w, y))
def redraw_window(surface):
global rows, snakes, snacks
surface.fill((0, 0, 0))
for i, s1 in enumerate(snakes):
s1.draw(surface)
s1.snack.draw(surface)
draw_grid(width, surface)
pygame.display.update()
class Cube:
rows = 20
w = 500
def __init__(self, position, color=(255, 0, 0)):
self.pos = position
self.color = color
def draw(self, surface):
dis = self.w // self.rows
i = self.pos[0]
j = self.pos[1]
pygame.draw.rect(surface, self.color, (i * dis + 1, j * dis + 1, dis - 2, dis - 2))
class Snake:
def __init__(self, pos):
self.head = Cube(pos)
self.body = []
self.body.append(self.head)
self.dirnx = 0
self.dirny = 1
self.added_cube = False
self.snack = Cube(randomSnack(rows), color=(0, 255, 0))
self.time = 50
def change_dir(self, direction_x, direction_y):
self.dirnx = direction_x
self.dirny = direction_y
def move(self):
self.head = self.body[-1]
# new_x, new_y = (self.head.pos[0] + self.dirnx) % rows, (self.head.pos[1] + self.dirny) % rows # add this to stop death from wall hit
new_x, new_y = (self.head.pos[0] + self.dirnx), (self.head.pos[1] + self.dirny)
c1 = Cube([new_x, new_y])
self.body.append(c1)
if not self.added_cube:
del self.body[0]
self.added_cube = False
def add_cube(self):
self.added_cube = True
def draw(self, surface):
for i, cube in enumerate(self.body):
cube.draw(surface)
def randomSnack(rows):
x = random.randrange(rows)
y = random.randrange(rows)
return [x, y]
def check_dir_changed():
for event in pygame.event.get():
keys = pygame.key.get_pressed()
for snake in snakes:
for key in keys:
if keys[pygame.K_LEFT]:
snake.change_dir(-1, 0)
elif keys[pygame.K_RIGHT]:
snake.change_dir(1, 0)
elif keys[pygame.K_UP]:
snake.change_dir(0, -1)
elif keys[pygame.K_DOWN]:
snake.change_dir(0, 1)
def eval_genomes(genomes, config):
global width, rows, snakes, snacks, gen
gen += 1
width = 500
rows = 20
win = pygame.display.set_mode((width, width))
nets = []
snakes = []
snacks = []
ge = []
for genome_id, genome in genomes:
genome.fitness = 1 # start with fitness level of 1
net = neat.nn.FeedForwardNetwork.create(genome, config)
nets.append(net)
start_position_x, start_position_y = random.randrange(0, 20), random.randrange(0, 20)
snakes.append(Snake([start_position_x, start_position_y]))
ge.append(genome)
clock = pygame.time.Clock()
while True and len(snakes) > 0:
pygame.time.delay(50)
clock.tick(10)
check_dir_changed()
for i, snake in enumerate(snakes):
# send info and determine from network what direction to go
output = nets[snakes.index(snake)].activate(
(snake.dirnx, snake.dirny, snake.snack.pos[0], snake.snack.pos[1],
snake.head.pos[0], snake.head.pos[1], distance.euclidean(snake.snack.pos, snake.head.pos),
distance.euclidean(snake.snack.pos[0], snake.head.pos[0]),
distance.euclidean(snake.snack.pos[1], snake.head.pos[1])))
# get the right move to make
max_output = -2
best_output = 0
for j, out in enumerate(output):
if out > max_output:
max_output = out
best_output = j
# 0 is right, 1 is left, 2 is down, 3 is up
if best_output == 0:
snake.change_dir(1, 0)
elif best_output == 1:
snake.change_dir(-1, 0)
elif best_output == 2:
snake.change_dir(0, 1)
elif best_output == 3:
snake.change_dir(0, -1)
snake.move()
# take 1 from the current snake's time, this stops snakes running around forever
snake.time -= 1
# add fitness depending how close snake is to the snack
ge[snakes.index(snake)].fitness += 20 - distance.euclidean(snake.snack.pos, snake.head.pos)
# if snake head eats snack
if snake.body[-1].pos == snake.snack.pos:
ge[snakes.index(snake)].fitness += 1000
snake.time += 40 # give snake more time since they got a snack
snake.add_cube()
snake.snack = Cube(randomSnack(rows), color=(0, 255, 0))
# if snake ran out of time without getting snack
if snake.time < 1:
ge[snakes.index(snake)].fitness -= 5
nets.pop(snakes.index(snake))
ge.pop(snakes.index(snake))
snakes.pop(snakes.index(snake))
break
# if snake hits a wall
if snake.body[-1].pos[0] > 20 or snake.body[-1].pos[0] < 0 or snake.body[-1].pos[1] > 20 or snake.body[-1].pos[1] < 0:
ge[snakes.index(snake)].fitness -= 1000
nets.pop(snakes.index(snake))
ge.pop(snakes.index(snake))
snakes.pop(snakes.index(snake))
break
# if snake eats itself
for x in range(len(snake.body) - 1):
if snake.body[x].pos == snake.body[-1].pos:
ge[snakes.index(snake)].fitness -= 10
nets.pop(snakes.index(snake))
ge.pop(snakes.index(snake))
snakes.pop(snakes.index(snake))
print('Score: ', len(snake.body))
break
redraw_window(win)
pass
def run(config_file):
config = neat.config.Config(neat.DefaultGenome, neat.DefaultReproduction,
neat.DefaultSpeciesSet, neat.DefaultStagnation,
config_file)
# Create the population, which is the top-level object for a NEAT run.
p = neat.Population(config)
# Add a stdout reporter to show progress in the terminal.
p.add_reporter(neat.StdOutReporter(True))
stats = neat.StatisticsReporter()
p.add_reporter(stats)
# p.add_reporter(neat.Checkpointer(5))
# Run for up to 50 generations.
winner = p.run(eval_genomes, 100)
# show final stats
print('\nBest genome:\n{!s}'.format(winner))
if __name__ == '__main__':
local_dir = os.path.dirname(__file__)
config_path = os.path.join(local_dir, 'config-feedforward.txt')
run(config_path)
[NEAT]
fitness_criterion = max
fitness_threshold = 10000000
pop_size = 20
reset_on_extinction = True
[DefaultGenome]
# node activation options
activation_default = sigmoid
activation_mutate_rate = 0.05
activation_options = sigmoid gauss
#abs clamped cube exp gauss hat identity inv log relu sigmoid sin softplus square tanh
# node aggregation options
aggregation_default = random
aggregation_mutate_rate = 0.05
aggregation_options = sum product min max mean median maxabs
# node bias options
bias_init_mean = 0.05
bias_init_stdev = 1.0
bias_max_value = 30.0
bias_min_value = -30.0
bias_mutate_power = 0.5
bias_mutate_rate = 0.7
bias_replace_rate = 0.1
# genome compatibility options
compatibility_disjoint_coefficient = 1.0
compatibility_weight_coefficient = 0.5
# connection add/remove rates
conn_add_prob = 0.5
conn_delete_prob = 0.5
# connection enable options
enabled_default = True
enabled_mutate_rate = 0.5
feed_forward = False
#initial_connection = unconnected
initial_connection = partial_nodirect 0.5
# node add/remove rates
node_add_prob = 0.5
node_delete_prob = 0.2
# network parameters
num_hidden = 0
num_inputs = 9
num_outputs = 4
# node response options
response_init_mean = 1.0
response_init_stdev = 0.05
response_max_value = 30.0
response_min_value = -30.0
response_mutate_power = 0.1
response_mutate_rate = 0.75
response_replace_rate = 0.1
# connection weight options
weight_init_mean = 0.1
weight_init_stdev = 1.0
weight_max_value = 30
weight_min_value = -30
weight_mutate_power = 0.5
weight_mutate_rate = 0.8
weight_replace_rate = 0.1
[DefaultSpeciesSet]
compatibility_threshold = 2.5
[DefaultStagnation]
species_fitness_func = max
max_stagnation = 50
species_elitism = 0
[DefaultReproduction]
elitism = 3
survival_threshold = 0.3
I'm currently in the process of creating a Snake game and I want to create a food generator that generates an apple every 10 seconds based on my in-game timer. The timer counts down from 60 to 0(when the game ends) and I want an new apple to generate every 10 seconds, keeping the old one even if it hasn't been eaten. I don't know how to approach this and could use some help. Here is my full program.
Edit: this is a beginner Computer Science school project so the more basic the better.
import random
import pygame
pygame.init()
#---------------------------------------#
#
# window properties #
width = 640 #
height = 480
game_window=pygame.display.set_mode((width,height))
black = ( 0, 0, 0) #
#---------------------------------------#
# snake's properties
outline=0
body_size = 9
head_size = 10
apple_size = 8
speed_x = 8
speed_y = 8
dir_x = 0
dir_y = -speed_y
segx = [int(width/2.)]*3
segy = [height, height + speed_y, height + 2*speed_y]
segments = len(segx)
apple_counter = 0
grid_step = 8
regular_font = pygame.font.SysFont("Andina",18)
blue = [11, 90, 220]
clock = pygame.time.Clock()
time = 60
fps = 25
time = time + 1.0/fps
text = regular_font.render("Time from start: "+str(int(time)), 1, blue)
text2 = regular_font.render("Score: "+str(int(apple_counter)), 1, blue)
apple_x = random.randrange(0, 640, grid_step)
apple_y = random.randrange(0, 480, grid_step)
apple_colour = (255,0,0)
def redraw_game_window():
game_window.fill(black)
for i in range(segments):
segment_colour = (random.randint(1,50),random.randint(100,150),random.randint(1,50))
head_colour = (random.randint(180,220),random.randint(180,220),random.randint(1,15))
apple_colour = (255,0,0)
pygame.draw.circle(game_window, segment_colour, (segx[i], segy[i]), body_size, outline)
pygame.draw.circle(game_window, head_colour, (segx[0], segy[0]), head_size, outline)
game_window.blit(text, (530, 20))
game_window.blit(text2, (30, 20))
pygame.draw.circle(game_window, apple_colour, (apple_x, apple_y), apple_size, outline)
pygame.display.update()
exit_flag = False
print "Use the arrows and the space bar."
print "Hit ESC to end the program."
########################################################## TIMER/CONTROLS
while exit_flag == False:
redraw_game_window()
clock.tick(fps)
time = time - 1.00/fps
text = regular_font.render("Time: "+str(int(time)), 1, blue)
text2 = regular_font.render("Score: "+str(int(apple_counter)), 1, blue)
if time < 0.1:
print "Game Over"
exit_flag = True
pygame.event.get()
keys = pygame.key.get_pressed()
if time ==
if keys[pygame.K_ESCAPE]:
exit_flag = True
if keys[pygame.K_LEFT] and dir_x != speed_x:
dir_x = -speed_x
dir_y = 0
if keys[pygame.K_RIGHT] and dir_x != -speed_x:
dir_x = speed_x
dir_y = 0
if keys[pygame.K_UP] and dir_y != speed_x:
dir_x = 0
dir_y = -speed_y
if keys[pygame.K_DOWN] and dir_y != -speed_x:
dir_x = 0
dir_y = speed_y
############################################################ SNAKE MOVEMENT
for i in range(segments-1,0,-1):
segx[i]=segx[i-1]
segy[i]=segy[i-1]
segx[0] = segx[0] + dir_x
segy[0] = segy[0] + dir_y
############################################################ COLLISION
for i in range(segments-1, 3, -1):
if segments > 3:
if segx[0] == segx[i] and segy[0] == segy[i]:
print "You have collided into yourself, Game Over."
exit_flag = True
############################################################# BORDERS
if segx[0] > 640 or segx[0] < 0:
print "Game Over, you left the borders."
break
if segy[0] > 480 or segy[0] < 0:
print "Game Over, you left the borders."
break
############################################################# APPLE DETECT
for i in range (0 , 13):
if segx[0] == apple_x + i and segy[0] == apple_y + i:
segments = segments + 1
segx.append(segx[-1])
segy.append(segy[-1])
apple_counter = apple_counter + 1
if segx[0] == apple_x - i and segy[0] == apple_y - i:
segments = segments + 1
segx.append(segx[-1])
segy.append(segy[-1])
apple_counter = apple_counter + 1
#############################################################
pygame.quit()
You either
A) use pygame.time.set_timer to call a function every 10 seconds to spawn food, and every 60 seconds to end the round.
or
B) compare get_ticks()
def new_round():
last_apple = pygame.time.get_ticks() + 10*1000
while true:
now = pygame.time.get_ticks()
if now - last_apple >= 1000:
spawn_apple()
last_apple = now
if now - round_start >= 60*1000:
round_end()
any help you can give me would be great. I am working on a simple game in python. I would like to have a countdown timer running on the screen. Based on other questions answered on this site, I think I have the code mostly correct, the problem I am having is that I am running the timer code using a "for" loop. I am not really sure why it is not working for me at the moment, when I run the game, I do not get any errors, the countdown displays but it has only counted down one second and it sticks on this time (01:29). Any suggestions would be really appreciated. The code that I am struggling with is towards the end of the program in a section called """Timer Countdown""" in the main loop for the game (line 354). Many thanks.
# Ice Hockey Game
from livewires import games, color
from tkinter import*
import pygame
import math, random
import os
import sys
import time
pygame.init()
games.init(screen_width = 1016, screen_height = 511, fps = 50)
################################################################################
"""timer variables"""
################################################################################
clock = pygame.time.Clock()
font = pygame.font.Font(None, 25)
red = ( 255, 0, 0)
frame_count = 0
frame_rate = 50
start_time = 90
done= False
output_string = ""
################################################################################
"""Score display variables"""
################################################################################
right_score = games.Text(value = 0, size = 25, color = color.black,
top = 30, right = games.screen.width - 250,
is_collideable = False)
games.screen.add(right_score)
left_score = games.Text(value = 0, size = 25, color = color.black,
top = 30, right = 250,
is_collideable = False)
games.screen.add(left_score)
player1_message = games.Message(value = "Player 1 Score",
size = 35,
color = color.black,
x = 250,
y = 15,
lifetime = 100000000,
is_collideable = False)
games.screen.add(player1_message)
player2_message = games.Message(value = "Player 2 Score",
size = 35,
color = color.black,
x = 750,
y = 15,
lifetime = 100000000,
is_collideable = False)
games.screen.add(player2_message)
###############################################################################
"""Player 1 and Player 2 WIN messages"""
###############################################################################
p1_won_message = games.Message(value = "Player 1 Wins!!!",
size = 100,
color = color.blue,
x = games.screen.width/2,
y = games.screen.height/2,
lifetime = 500,
after_death = games.screen.quit,
is_collideable = False)
p2_won_message = games.Message(value = "Player 2 Wins!!!",
size = 100,
color = color.blue,
x = games.screen.width/2,
y = games.screen.height/2,
lifetime = 500,
after_death = games.screen.quit,
is_collideable = False)
##############################################################################
"""Goal animation images and functions"""
################################################################################
"""Animation images"""
goal_anim_files = ["Goal_Anim_001.bmp", "Goal_Anim_002.bmp", "Goal_Anim_003.bmp",
"Goal_Anim_004.bmp","Goal_Anim_005.bmp","Goal_Anim_006.bmp",
"Goal_Anim_007.bmp","Goal_Anim_008.bmp","Goal_Anim_009.bmp","Goal_Anim_010.bmp", "Goal_Anim_011.bmp", "Goal_Anim_012.bmp", "Goal_Anim_013.bmp",
"Goal_Anim_014.bmp","Goal_Anim_015.bmp","Goal_Anim_016.bmp",
"Goal_Anim_017.bmp","Goal_Anim_018.bmp","Goal_Anim_019.bmp","Goal_Anim_020.bmp", "Goal_Anim_021.bmp","Goal_Anim_022.bmp", "Goal_Anim_023.bmp",
"Goal_Anim_024.bmp","Goal_Anim_025.bmp"]
def goal_msg_left(self):
global goal_anim_left
goal_anim_left = games.Animation(images = goal_anim_files, x = 250,
y= games.screen.height/2, n_repeats = 1,
repeat_interval = 1, is_collideable = False)
#print("inside goal_msg_left")
def goal_msg_right(self):
global goal_anim_right
goal_anim_right = games.Animation(images = goal_anim_files, x = 750,
y= games.screen.height/2, n_repeats = 1,
repeat_interval = 1, is_collideable = False)
#print("inside goal_msg_right")
class Leftgoalanim(games.Animation):
"""goal animation"""
def update(self):
self.check_collide()
def check_collide(self):
for player1 in self.overlapping_sprites:
player1.handle_player_collide()
for player2 in self.overlapping_sprites:
player2.handle_player_collide()
class Leftgoal(games.Sprite):
def update(self):
self.check_collide()
self.check_goal()
def check_collide(self):
""" Check for collision with puck. """
for puck in self.overlapping_sprites:
puck.handle_collide()
def handle_collide(self):
""" Move to a random screen location. """
self.dx = -self.dx
self.dy = 0
self.x = games.screen.width/2
self.y = games.screen.height/2
def check_goal(self):
""" Check if left goal. """
global goal_anim_left
for puck in self.overlapping_sprites:
#puck.handle_collide()
goal_msg_left(self)
games.screen.add(goal_anim_left)
right_score.value += 1
if right_score.value >= 10:
games.screen.add(p2_won_message)
class Rightgoal(games.Sprite):
def update(self):
self.check_collide()
self.check_goal()
def check_collide(self):
""" Check for collision with puck. """
for puck in self.overlapping_sprites:
puck.handle_collide()
def handle_collide(self):
""" Move to a random screen location. """
self.dx = -self.dx
self.dy = 0
self.x = games.screen.width/2
self.y = games.screen.height/2
def check_goal(self):
""" Check if left goal. """
for puck in self.overlapping_sprites:
#puck.handle_collide()
goal_msg_right(self)
games.screen.add(goal_anim_right)
left_score.value += 1
if left_score.value >= 10:
games.screen.add(p1_won_message)
################################################################################
"""Classes for Players sprites"""
################################################################################
class Player1(games.Sprite):
"""move the player 1"""
VELOCITY_STEP = .03
VELOCITY_MAX = 3
def update(self):
if games.keyboard.is_pressed(games.K_w):
self.y -= 3
if games.keyboard.is_pressed(games.K_s):
self.y += 3
if games.keyboard.is_pressed(games.K_a):
self.x -= 3
if games.keyboard.is_pressed(games.K_d):
self.x += 3
if self.right > 940:
self.x = 913
if self.left < 85:
self.x = 108
if self.bottom > games.screen.height:
self.y = 475
if self.top < 0:
self.y = 50
self.check_collide()
def check_collide(self):
""" Check for collision with puck. """
for puck in self.overlapping_sprites:
puck.handle_collide()
def handle_player_collide(self):
self.dx = -self.dx
self.dy = 0
def handle_collide(self):
""" Move to a random screen location. """
self.dx = -self.dx
self.dy = 0
class Player2(games.Sprite):
"""move the player 2"""
VELOCITY_STEP = .03
VELOCITY_MAX = 3
def update(self):
if games.keyboard.is_pressed(games.K_UP):
self.y -= 3
if games.keyboard.is_pressed(games.K_DOWN):
self.y += 3
if games.keyboard.is_pressed(games.K_LEFT):
self.x -= 3
if games.keyboard.is_pressed(games.K_RIGHT):
self.x += 3
if self.right > 940:
self.x = 913
if self.left < 85:
self.x = 108
if self.bottom > games.screen.height:
self.y = 475
if self.top < 0:
self.y = 50
self.check_collide()
def check_collide(self):
""" Check for collision with puck. """
for puck in self.overlapping_sprites:
puck.handle_collide()
def handle_collide(self):
""" Move to a random screen location. """
self.dx = -self.dx
self.dy = 0
def handle_player_collide(self):
self.dx = -self.dx
self.dy = 0
################################################################################
"""Class for Puck"""
################################################################################
class Puck(games.Sprite):
""" A bouncing puck. """
def update(self):
""" Reverse a velocity component if edge of screen reached. """
if self.right > games.screen.width or self.left < 0:
self.dx = -self.dx
if self.bottom > games.screen.height or self.top < 0:
self.dy = -self.dy
def handle_collide(self):
""" reverses x direction when collides. """
self.dx = -self.dx
self.dy = self.dy
def handle_goal(self):
"""what happens to the puck when goal"""
self.dx = -self.dx
self.dy = self.dy
################################################################################
"""Main Loop For Game"""
################################################################################
def main():
wall_image = games.load_image("Table_002_1016H_511W.jpg", transparent = False)
games.screen.background = wall_image
#########image left and right goal images and add them to game##########
left_goal_image = games.load_image("Goal_left_cropped.bmp")
the_left_goal = Leftgoal(image = left_goal_image,
x = 40,
y = games.screen.height/2,
)
right_goal_image = games.load_image("Goal_right_cropped.bmp")
the_right_goal = Rightgoal(image = right_goal_image,
x = 976,
y = games.screen.height/2,
)
#########player 1 import image and add to game##########################
player1_image = games.load_image("Player_red_half_50_75_Fixed.bmp")
the_player1 = Player1(image = player1_image,
x = games.screen.width/4,
y = games.screen.height/2)
games.screen.add(the_player1)
#########player 2 import image and add to game##########################
player2_image = games.load_image("Player_green_half_50_75_flipped_fixed.bmp")
the_player2 = Player2(image = player2_image,
x = 750,
y = games.screen.height/2)
games.screen.add(the_player2)
################Import image for the Puck and Add to the game###########
puck_image = games.load_image("puck_small.png", transparent = True)
the_puck = Puck(image = puck_image,
x = games.screen.width/2,
y = games.screen.height/2,
dx = -3,
dy = 3)
counter = 0
###########################################################################
"""TIMER COUNTDOWN"""
###########################################################################
clock = pygame.time.Clock()
font = pygame.font.Font(None, 25)
red = ( 255, 0, 0)
frame_count = 0
frame_rate = 50
start_time = 90
done= False
output_string = ""
for n in reversed(range(0, start_time)):
total_seconds = frame_count // frame_rate
minutes = total_seconds // 60
seconds = total_seconds % 60
output_string = "Time: {0:02}:{1:02}".format(minutes, seconds)
# Blit to the screen
text = font.render(output_string, True, red)
#screen.blit(text, [250, 250])
# --- Timer going down ---
# --- Timer going up ---
# Calculate total seconds
total_seconds = start_time - (frame_count // frame_rate)
if total_seconds < 0:
total_seconds = 0
# Divide by 60 to get total minutes
minutes = total_seconds // 60
# Use modulus (remainder) to get seconds
seconds = total_seconds % 60
# Use python string formatting to format in leading zeros
output_string = "Time left: {0:02}:{1:02}".format(minutes, seconds)
# Blit to the screen
text = font.render(output_string, True, red)
#screen.blit(text, [250, 280])
# ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT
frame_count += 1
# Limit to 20 frames per second
clock.tick_busy_loop(50)
# Go ahead and update the screen with what we've drawn.
pygame.display.flip()
###Timer Display###
timer_text = games.Message(value = "TIME",
size = 45,
color = color.red,
top = 30, right = games.screen.width/2,
lifetime = 100000000,
is_collideable = False)
timer_countdown = games.Text(value = output_string, size = 25, color = color.red,
top = 60, right = 600,
is_collideable = False)
games.screen.add(timer_countdown)
games.screen.add(timer_text)
games.screen.add(the_left_goal)
games.screen.add(the_right_goal)
games.screen.add(the_puck)
games.screen.event_grab = True
games.mouse.is_visible = False
games.screen.mainloop()
# start the game
main()
Using pygame.time.get_ticks() to store a start time,
calling this again every frame will give a time greater than your stored start time, simply subtract your start time from this to get the interval in milliseconds since the timer started
As #jonrsharpe said however, it should be a code "sample", not the whole sodding thing, As such I might not have actually answered your question, I can't tell because I'm not going to read and understand the whole code.