How do I create multiple levels in pygame? - python-2.7

I can't get my "world_data2" and "world_data3" to draw to the screen. only the "world_data" at index position 0 of the "levels" list draws. Everything else seems to be working. The bats and the doors change in every level, but the tile layout stays exactly the same. Is it possibly something to do with my "reset_level" function? or my world class?
Improved code:
# Importing the pygame library
import pygame
# Initializing pygame
pygame.init()
# Clock and frame rate
clock = pygame.time.Clock()
fps = 60
# Creating the game window
screen_width = 1500
screen_height = 1000
screen = pygame.display.set_mode((screen_width, screen_height))
# Setting game window caption
pygame.display.set_caption('Castle Escape')
# Define game variables
tile_size = 50
game_over = 0
main_menu = True
current_level_index = 0
total_levels = 2
# Loading images
background_img = pygame.image.load('Assets/Images/purplebackground.jpg')
restart_img = pygame.image.load('Assets/Images/Sprites/Buttons/restart.png')
restart_img = pygame.transform.scale(restart_img, (80, 40))
play_img = pygame.image.load('Assets/Images/Sprites/Buttons/play.png')
play_img = pygame.transform.scale(play_img, (350, 190))
exit_img = pygame.image.load('Assets/Images/Sprites/Buttons/exit.png')
exit_img = pygame.transform.scale(exit_img, (350, 190))
controls_img = pygame.image.load('Assets/Images/Sprites/Buttons/controls.png')
controls_img = pygame.transform.scale(controls_img, (350, 190))
settings_img = pygame.image.load('Assets/Images/Sprites/Buttons/settings.png')
settings_img = pygame.transform.scale(settings_img, (350, 190))
menu_img = pygame.image.load('Assets/Images/Sprites/Buttons/menu.png')
menu_img = pygame.transform.scale(menu_img, (80, 40))
# Instances for groups
bat_group = pygame.sprite.Group()
door_group = pygame.sprite.Group()
# Function to draw grid
def draw_grid():
for line in range(0, 30):
pygame.draw.line(screen, (255, 255, 255), (0, line * tile_size), (screen_width, line * tile_size))
pygame.draw.line(screen, (255, 255, 255), (line * tile_size, 0), (line * tile_size, screen_height))
# Function to reset levels
def reset_level(current_level_index):
# Reset player position
player.reset(100, screen_height - 130)
# Empty groups
bat_group.empty()
door_group.empty()
# Load in level data and create world
if current_level_index <= total_levels:
level = levels[current_level_index]
world = World(level)
return world
# Class for world map
class World:
# Constructor
def __init__(self, data):
# List to store locations of tiles
self.tile_list = []
# Load images
ground_img = pygame.image.load('Assets/Medieval Tileset/PNG/Tiles/tile59.png')
ground2_img = pygame.image.load('Assets/Medieval Tileset/PNG/Tiles/tile34.png')
leftwall_img = pygame.image.load('Assets/Medieval Tileset/PNG/Tiles/tile56.png')
rightwall_img = pygame.image.load('Assets/Medieval Tileset/PNG/Tiles/tile58.png')
ceiling_img = pygame.image.load('Assets/Medieval Tileset/PNG/Tiles/tile146.png')
# Loop to run through each row of world grid
row_count = 0
for row in data:
# Loop to run through each column in each row of world grid
col_count = 0
for tile in row:
if tile == 1:
# Scale images to 50 x 50px
img = pygame.transform.scale(ground_img, (tile_size, tile_size))
# Take rectangle
img_rect = img.get_rect()
# x and y coordinates for rectangle
img_rect.x = col_count * tile_size
img_rect.y = row_count * tile_size
tile = (img, img_rect)
self.tile_list.append(tile)
if tile == 2:
# Scale images to 50 x 50px
img = pygame.transform.scale(leftwall_img, (tile_size, tile_size))
# Take rectangle
img_rect = img.get_rect()
# x and y coordinates for rectangle
img_rect.x = col_count * tile_size
img_rect.y = row_count * tile_size
tile = (img, img_rect)
self.tile_list.append(tile)
if tile == 3:
# Scale images to 50 x 50px
img = pygame.transform.scale(rightwall_img, (tile_size, tile_size))
# Take rectangle
img_rect = img.get_rect()
# x and y coordinates for rectangle
img_rect.x = col_count * tile_size
img_rect.y = row_count * tile_size
tile = (img, img_rect)
self.tile_list.append(tile)
if tile == 4:
# Scale images to 50 x 50px
img = pygame.transform.scale(ceiling_img, (tile_size, tile_size))
# Take rectangle
img_rect = img.get_rect()
# x and y coordinates for rectangle
img_rect.x = col_count * tile_size
img_rect.y = row_count * tile_size
tile = (img, img_rect)
self.tile_list.append(tile)
if tile == 5:
# Scale images to 50 x 50px
img = pygame.transform.scale(ground2_img, (tile_size, tile_size))
# Take rectangle
img_rect = img.get_rect()
# x and y coordinates for rectangle
img_rect.x = col_count * tile_size
img_rect.y = row_count * tile_size
tile = (img, img_rect)
self.tile_list.append(tile)
if tile == 6:
# Create instance of bat enemy
bat = Enemy(col_count * tile_size, row_count * tile_size)
bat_group.add(bat)
if tile == 7:
# Create instance of door
door = Doors(col_count * tile_size, row_count * tile_size - 50)
door_group.add(door)
col_count += 1
row_count += 1
# Method to draw tiles to screen
def drawWorld(self):
# Loop to iterate through tile_list
for tile in self.tile_list:
screen.blit(tile[0], tile[1])
pygame.draw.rect(screen, (255, 255, 255), tile[1], 2)
# Class for buttons
class Button:
def __init__(self, x, y, image):
self.image = image
# Create rectangle
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
# Check whether mouse click occurs
self.clicked = False
# Draw method
def draw(self):
# Variable holds whether restart button been clicked or not
action = False
# Get mouse position
pos = pygame.mouse.get_pos()
# Check mouseover and clicked conditions
if self.rect.collidepoint(pos):
if pygame.mouse.get_pressed()[0] == 1 and self.clicked == False:
self.clicked = True
action = True
# Make sure button can only be clicked once
if pygame.mouse.get_pressed()[0] == 0:
self.clicked = False
# Draw button
screen.blit(self.image, self.rect)
return action
# Class for player (sprite)
class Player:
# Spawn Player
def __init__(self, x, y):
# Call reset method
self.reset(x, y)
def updatePlayer(self, game_over):
dx = 0 # move along x
dy = 0 # move along y
run_slowDown = 5 # Slow down run animation
if game_over == 0:
# Key controls
key = pygame.key.get_pressed()
# Move player left
if key[pygame.K_LEFT]:
dx -= 3
self.counter += 1
self.direction = -1
# Move player right
if key[pygame.K_RIGHT]:
dx += 3
self.counter += 1
self.direction = 1
# Show idle image if no keys are being pressed
if key[pygame.K_LEFT] == False and key[pygame.K_RIGHT] == False:
self.counter = 0
self.index = 0
if self.direction == 0 or self.direction == 1:
self.image = pygame.image.load('Assets/Images/Sprites/Warrior/Idle/idle1.png')
self.image = pygame.transform.scale(self.image, (60, 90))
if self.direction == -1:
self.image = pygame.image.load('Assets/Images/Sprites/Warrior/Idle/idle1.png')
self.image = pygame.transform.scale(self.image, (60, 90))
self.image = pygame.transform.flip(self.image, True, False)
# Make player jump
self.rect.y += self.vel_y
if key[pygame.K_SPACE] and self.jumped == False and self.in_air == False:
self.vel_y = -12
self.jumped = True
if not key[pygame.K_SPACE]:
self.jumped = False
# Handle animations
if self.counter > run_slowDown:
self.counter = 0
self.index += 1
if self.index >= len(self.transformed_rightRun):
self.index = 0
if self.direction == 1:
self.image = self.transformed_rightRun[self.index]
if self.direction == -1:
self.image = self.images_leftRun[self.index]
# Add gravity
self.vel_y += 1
# Add terminal velocity
if self.vel_y > 2:
self.vel_y = 2
dy += self.vel_y
# Check for collision with tiles
self.in_air = True
for tile in world.tile_list:
# Check for collision in x-direction
if tile[1].colliderect(self.rect.x + dx, self.rect.y, self.width, self.height):
dx = 0
# Check for collision in y-direction
if tile[1].colliderect(self.rect.x, self.rect.y + dy, self.width, self.height):
# Check if hitting head on tile (jumping)
if self.vel_y < 0:
dy = tile[1].bottom - self.rect.top
self.vel_y = 0
# Check if landing on tile (falling)
elif self.vel_y >= 0:
dy = tile[1].top - self.rect.bottom
self.vel_y = 0
# Make sure player can only jump once
self.in_air = False
# Check for collision with enemies
if pygame.sprite.spritecollide(self, bat_group, False):
game_over = -1 # Value of -1 triggers game over
# Check collision with doors
if pygame.sprite.spritecollide(self, door_group, False):
game_over = 1 # Value of 1 means player has completed level
# update player coordinates
self.rect.x += dx
self.rect.y += dy
elif game_over == -1:
# Turn player into ghost
self.image = self.dead_image
# Make ghost float up
if self.rect.y > 200:
self.rect.y -= 5
# Draw player to screen
screen.blit(self.image, self.rect)
# Draw rectangle
pygame.draw.rect(screen, (255, 255, 255), self.rect, 2)
return game_over
# Method to reset game
def reset(self, x, y):
# Right run animation list
self.images_rightRun = []
# Append all right run animation images to list
self.images_rightRun.append(pygame.image.load('Assets/Images/Sprites/Warrior/Run/run1.png'))
self.images_rightRun.append(pygame.image.load('Assets/Images/Sprites/Warrior/Run/run2.png'))
self.images_rightRun.append(pygame.image.load('Assets/Images/Sprites/Warrior/Run/run3.png'))
self.images_rightRun.append(pygame.image.load('Assets/Images/Sprites/Warrior/Run/run4.png'))
self.images_rightRun.append(pygame.image.load('Assets/Images/Sprites/Warrior/Run/run5.png'))
self.images_rightRun.append(pygame.image.load('Assets/Images/Sprites/Warrior/Run/run6.png'))
self.images_rightRun.append(pygame.image.load('Assets/Images/Sprites/Warrior/Run/run7.png'))
self.images_rightRun.append(pygame.image.load('Assets/Images/Sprites/Warrior/Run/run8.png'))
# New transformed right run list
self.transformed_rightRun = []
for img in self.images_rightRun:
self.transformed_rightRun.append(pygame.transform.scale(img, (60, 90)))
# Left run animation list
self.images_leftRun = []
for img in self.transformed_rightRun:
self.images_leftRun.append(pygame.transform.flip(img, True, False))
# Set index and counter of lists to 0
self.index = 0
self.counter = 0 # Counter controls speed of animation
# Load and scale ghost image
self.dead_image = pygame.image.load('Assets/Images/Sprites/Ghost/ghost.png')
self.dead_image = pygame.transform.scale(self.dead_image, (40, 60))
# Statement to display current sprite animation on screen
self.image = self.transformed_rightRun[self.index]
# Create player rectangle
self.rect = self.image.get_rect()
# Get x coordinate
self.rect.x = x
# Get y coordinate
self.rect.y = y
# Width and height for rectangle
self.width = self.image.get_width()
self.height = self.image.get_height()
# Set velocity in y direction to 0
self.vel_y = 0
# Player jump
self.jumped = False
# Player direction
self.direction = 0
# Check if player is in air
self.in_air = True
# Class for enemies
class Enemy(pygame.sprite.Sprite):
def __init__(self, x, y):
# Calling constructor from super class
pygame.sprite.Sprite.__init__(self)
# Load and scale bat images
self.image = pygame.image.load('Assets/Images/Sprites/Bat/Fly/fly2.png')
self.image = pygame.transform.scale(self.image, (50, 40))
# Flip bat image
self.left_image = pygame.transform.flip(self.image, True, False)
# Create rectangle
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
# Variables for movement
self.move_direction = 1
self.move_counter = 0
def update(self):
# Move bats left and right
self.rect.x += self.move_direction
self.move_counter += 1
if abs(self.move_counter) > 100:
self.move_direction *= -1
self.move_counter *= -1
# Flip bat images
if self.move_direction == -1:
self.image = self.left_image
if self.move_direction == 1:
self.image = pygame.transform.flip(self.left_image, True, False)
# Draw bat rectangle to screen
pygame.draw.rect(screen, (255, 255, 255), self.rect, 2)
# Class for enemies
class Doors(pygame.sprite.Sprite):
def __init__(self, x, y):
# Calling constructor from super class
pygame.sprite.Sprite.__init__(self)
# Load and scale door images
self.image = pygame.image.load('Assets/Medieval Tileset/PNG/Objects/door4.png')
self.image = pygame.transform.scale(self.image, (80, 100))
# Create rectangle
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
# Level 1 map
world_data1 = [
[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 1, 1, 1, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 1, 5, 5, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 7, 0, 1, 5, 5, 5, 5, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5],
]
# Level 2 map
world_data2 = [
[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 6, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5],
]
# Level 3 map
world_data3 = [
[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 1, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 5, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 1, 5, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 1, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 3],
[1, 1, 1, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5],
]
# Store level maps in list
levels = [
world_data1,
world_data2,
world_data3,
]
# Load in level data and create world
if current_level_index <= total_levels:
level = levels[current_level_index]
world = World(level)
# Create instance of button class
restart_button = Button(screen_width // 2 - 50, screen_height // 2 + 100, restart_img)
play_button = Button(screen_width // 2 - 550, screen_height // 2 - 220, play_img)
exit_button = Button(screen_width // 2 - 550, screen_height // 2 + 50, exit_img)
controls_button = Button(screen_width // 2 + 150, screen_height // 2 - 220, controls_img)
settings_button = Button(screen_width // 2 + 150, screen_height // 2 + 50, settings_img)
menu_button = Button(screen_width // 2 - 50, screen_height // 2 + 100, menu_img)
# Create instance of player class
player = Player(100, 800)
# main game loop
run = True
while run:
# Set internal clock
clock.tick(fps)
# Draw background to screen
screen.blit(background_img, (0, 0))
# Display buttons on main menu
if main_menu:
# If exit button is clicked, close game
if exit_button.draw():
run = False
# If play button is clicked, start game
if play_button.draw():
main_menu = False
controls_button.draw()
settings_button.draw()
else:
# Draw levels to screen
world.drawWorld()
# if the player dies, stop updating bats
if game_over == 0:
bat_group.update()
# Draw bats to screen
bat_group.draw(screen)
# Draw doors to screen
door_group.draw(screen)
# Draw player to screen and return game_over value
game_over = player.updatePlayer(game_over)
# if player dies, display restart button
if game_over == -1:
if restart_button.draw():
# Send player back to level 1
current_level_index = 0
reset_level(current_level_index)
game_over = 0
# If player has completed level, move to next level
if game_over == 1:
current_level_index += 1
if current_level_index <= total_levels:
reset_level(current_level_index)
game_over = 0
else:
# If player has completed final level, open main menu
if menu_button.draw():
main_menu = True
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.display.update()
pygame.quit()
Any help would be greatly appreciated. Thank you!

Keep in mind that your main loop logic is run at each frame, so here, at each frame you run level 1, then if game over == 1 you run level2 etc, so everything is reset all the time. I think your problem is there.
You could define a state that would hold the current level and use this.
For example:
levels= ( # store your levels in some convenient structure
World(world_data1),
World(world_data2),
World(world_data2),
)
current_level_index = 0 # The level state, initalized with the index of the first level
game_over = 0
while True:
level = levels[current_level_index] # use your state to get the level instead of naming it directly
level.drawWorld()
# whatever you need to do to update your level logic, move things etc
if game_over == 1:
# This just is a simplistic example implementation to illustrate a change of level
current_level_index += 1
This is just a trivial example but you can try to structure your code in this kind of way.

Related

How to write this interpolate function using OpenCV?

I want to optimize this code, in particular this function:
bool interpolate(const Mat &im, float ofsx, float ofsy, float a11, float a12, float a21, float a22, Mat &res)
{
bool ret = false;
// input size (-1 for the safe bilinear interpolation)
const int width = im.cols-1;
const int height = im.rows-1;
// output size
const int halfWidth = res.cols >> 1;
const int halfHeight = res.rows >> 1;
int dim = res.rows * res.cols;
float *out = res.ptr<float>(0);
for (int j=-halfHeight; j<=halfHeight; ++j)
{
const float rx = ofsx + j * a12;
const float ry = ofsy + j * a22;
#pragma omp simd
for(int i=-halfWidth; i<=halfWidth; ++i)
{
float wx = rx + i * a11;
float wy = ry + i * a21;
const int x = (int) floor(wx);
const int y = (int) floor(wy);
if (x >= 0 && y >= 0 && x < width && y < height)
{
// compute weights
wx -= x; wy -= y;
// bilinear interpolation
*out++ =
(1.0f - wy) * ((1.0f - wx) * im.at<float>(y,x) + wx * im.at<float>(y,x+1)) +
( wy) * ((1.0f - wx) * im.at<float>(y+1,x) + wx * im.at<float>(y+1,x+1));
} else {
*out++ = 0;
ret = true; // touching boundary of the input
}
}
}
return ret;
}
Can anybody please help to find an equivalent function in OpenCV for the code above? I'm not expert on image processing, so I don't really know what the fucntion above does in details, but I think this is a warp-affine transformation, even though I don't really know how to define an OpenCV equivalent.
It seems that the input images are the blurred image, the original image or small patches of it. The output result is always a small patch.
Here are some samples:
Sample 1:
Args:
ofx=175.497 ofsy=315.06 a11=1.69477 a12=0.0671724 a21=0.0679493 a22=1.56309
Input image:
Output image:
Sample 2:
Args:
ofx=572.121 ofsy=326.659 a11=0.871508 a12=0 a21=0.346405 a22=1.14744
Input image:
Output image:
Sample 3:
ofx=66.571 ofsy=148.991 a11=1.12027 a12=0.126609 a21=0.126609 a22=2.53436
Input image:
Output image:
These are different sections of the original code where the function is called:
// warp input according to current shape matrix
interpolate(wrapper.prevBlur, lx, ly, u11*ratio, u12*ratio, u21*ratio, u22*ratio, img);
Mat smoothed(patchImageSize, patchImageSize, CV_32FC1, (void *)&workspace.front());
// interpolate with det == 1
if (!interpolate(img, x, y, a11, a12, a21, a22, smoothed))
{
// subsample with corresponding scale
interpolate(smoothed, (float)(patchImageSize>>1), (float)(patchImageSize>>1), imageToPatchScale, 0, 0, imageToPatchScale, patch);
// ok, do the interpolation
interpolate(img, x, y, a11, a12, a21, a22, patch);
This is what happens when I try to use warpAffine in the following way:
// warp input according to current shape matrix
interpolate(wrapper.prevBlur, lx, ly, u11*ratio, u12*ratio, u21*ratio, u22*ratio, img);
Mat warp_mat( 2, 3, CV_32FC1 );
Mat myPatch(img.rows, img.cols, CV_32FC1);
warp_mat.at<float>(0,2) = lx;
warp_mat.at<float>(1,2) = ly;
warp_mat.at<float>(0,0) = u11*ratio;
warp_mat.at<float>(0,1) = u12*ratio;
warp_mat.at<float>(1,0) = u21*ratio;
warp_mat.at<float>(1,1) = u22*ratio;
warpAffine(wrapper.prevBlur, myPatch, warp_mat, myPatch.size());
The resulting myPatch matrix is a zero matrix, while img (obtained by interpolate) is:
[19.109245, 19.189388, 18.941183, 18.454611, 18.285404, 19.447983, 22.037096, 28.504759, 37.753605, 50.69936, 61.34388, 67.619637, 70.699326, 71.640556, 73.347702, 72.383781, 70.7649, 72.320709, 74.32235;
18.464636, 18.408369, 18.347059, 18.194805, 17.982847, 18.312258, 18.990305, 21.852564, 26.399525, 35.10569, 44.444019, 53.986103, 59.851856, 63.937149, 67.766968, 70.979973, 73.074722, 77.097763, 82.344398;
17.838448, 17.706562, 17.580456, 17.869242, 18.216852, 18.72654, 19.004158, 20.150208, 21.66539, 26.167187, 31.805283, 41.04277, 48.207466, 54.719109, 59.793156, 65.378006, 71.004974, 77.016037, 86.317352;
17.257101, 17.117496, 16.95055, 17.34347, 18.505379, 20.129673, 21.161978, 22.195414, 22.287436, 24.150574, 26.179817, 32.619934, 39.298115, 46.696926, 52.091522, 57.986988, 64.629898, 72.434052, 82.955505;
16.810595, 16.665813, 16.672272, 17.16098, 18.665346, 21.783976, 24.785789, 27.150511, 27.23918, 27.834826, 27.594404, 30.645121, 35.405987, 42.133587, 46.915634, 51.880707, 57.028702, 64.57579, 74.402069;
16.687065, 16.451401, 16.626608, 17.460049, 19.36956, 23.552647, 28.802736, 33.788773, 35.505379, 35.85894, 34.729523, 34.880505, 37.088661, 42.075432, 45.702, 49.056709, 51.509052, 56.637093, 63.660839;
16.802176, 16.594761, 16.863697, 18.126085, 20.491119, 25.517574, 32.737259, 40.572498, 45.324429, 46.528313, 45.586109, 44.153858, 43.667118, 46.450905, 48.539593, 50.182858, 50.18359, 51.575584, 54.267056;
17.036257, 17.025221, 17.271259, 18.925261, 22.124079, 27.620583, 35.921772, 46.177872, 54.232437, 57.583233, 57.648571, 55.857315, 53.885891, 54.148857, 55.00872, 54.9893, 52.946201, 50.873283, 49.034798;
17.337849, 17.61212, 18.028404, 19.572941, 23.455297, 29.841951, 38.668663, 49.819805, 60.617371, 66.327873, 68.025574, 66.935631, 64.995117, 63.513988, 63.28405, 62.325748, 58.940784, 53.796066, 48.033508;
17.798275, 18.203262, 19.018663, 20.718761, 24.611408, 31.378065, 40.706932, 51.637016, 63.323963, 71.373169, 74.578476, 74.412659, 74.106857, 72.411026, 71.710922, 70.007111, 66.181709, 58.721882, 50.149853;
18.593805, 19.017687, 20.172789, 22.093014, 25.971659, 32.813194, 41.989246, 52.252911, 62.929924, 71.418938, 76.355003, 77.044289, 78.709656, 78.83432, 78.581551, 76.614075, 72.71788, 63.598377, 52.698578;
19.567734, 20.197411, 21.640959, 24.039509, 27.603041, 34.091061, 42.821777, 52.127884, 61.030842, 68.610733, 73.860558, 75.530617, 78.25412, 81.30085, 82.840904, 80.822067, 76.685196, 67.430412, 54.54921;
21.115396, 21.835562, 23.40497, 26.244884, 30.036913, 35.568745, 43.308716, 51.656746, 58.69318, 64.595673, 69.845467, 72.11985, 74.878944, 79.890228, 83.964821, 82.866249, 77.71666, 68.196243, 55.256557;
23.264105, 24.024746, 25.705564, 28.513554, 32.514004, 37.26601, 43.47644, 50.611153, 56.786697, 61.13575, 66.052094, 69.762238, 71.692001, 76.810669, 81.848129, 82.157066, 76.844963, 66.500725, 54.042095;
26.102678, 26.758638, 28.201065, 30.806498, 34.584103, 38.752495, 43.416939, 48.890656, 54.433743, 58.482693, 63.515507, 69.373245, 71.917755, 74.965172, 78.791039, 79.034378, 73.354454, 62.917992, 50.983219;
29.008026, 30.016344, 30.787025, 32.692429, 35.850079, 39.365425, 42.956245, 46.993965, 51.688225, 56.120068, 61.624519, 69.804024, 74.923134, 76.170395, 76.252747, 74.715118, 68.599701, 58.000847, 47.082359;
31.630077, 33.315144, 33.247631, 33.903202, 36.094364, 38.939133, 42.000217, 45.338474, 49.197887, 53.639317, 59.658398, 69.140472, 77.870468, 79.725624, 75.932251, 69.885872, 62.522583, 52.486378, 42.571148;
34.113537, 36.435402, 35.544792, 34.225368, 35.189747, 37.445477, 40.579632, 44.427345, 48.191299, 52.085419, 57.660496, 66.887024, 77.807755, 81.70005, 76.676743, 66.486168, 56.192219, 46.825108, 38.276539;
37.42725, 39.82682, 37.698589, 34.016525, 33.155304, 35.16758, 39.039139, 44.336964, 49.359722, 52.590809, 56.610603, 64.08419, 74.419289, 80.603294, 76.006302, 63.653465, 50.843102, 41.247444, 34.471062]
Update after comment:
These are results by using [[1, 0, 0], [0, 1, 0]] with the following code:
Mat warp_mat( 2, 3, CV_32FC1 );
Mat myPatch(img.rows, img.cols, CV_32FC1);
warp_mat.at<float>(0,0) = 1; //u11*ratio
warp_mat.at<float>(0,1) = 0; //u12*ratio
warp_mat.at<float>(0,2) = 0+(img.cols >> 1); //lx
warp_mat.at<float>(1,0) = 0; //u21*ratio
warp_mat.at<float>(1,1) = 1; //u22*ratio
warp_mat.at<float>(1,2) = 0+(img.rows >> 1); //ly
warpAffine(wrapper.prevBlur, myPatch, warp_mat, myPatch.size());
interpolate(wrapper.prevBlur, 0, 0, 1, 0, 0, 1, img);
std::cout<<"img="<<std::endl<<img<<std::endl;
std::cout<<"myPatch="<<std::endl<<myPatch<<std::endl;
The result is the same, but if I try to use:
warp_mat.at<float>(0,0) = 1; //u11*ratio
warp_mat.at<float>(0,1) = 1; //u12*ratio
warp_mat.at<float>(0,2) = 0+(img.cols >> 1); //lx
warp_mat.at<float>(1,0) = 0; //u21*ratio
warp_mat.at<float>(1,1) = 1; //u22*ratio
warp_mat.at<float>(1,2) = 0+(img.rows >> 1); //ly
warpAffine(wrapper.prevBlur, myPatch, warp_mat, myPatch.size());
interpolate(wrapper.prevBlur, 0, 0, 1, 1, 0, 1, img);
The matrix are "mirrored":
myPatch=
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 2.4431293, 2.1086276, 1.7749974, 1.5721301, 1.5403291, 1.6410155, 1.8406107, 2.1113796, 2.3246853, 2.274801;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.3276107, 2.0702307, 1.8100098, 1.6615094, 1.6572961, 1.7410251, 1.8701531, 2.0462515, 2.1933937;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.3676813, 2.1666555, 1.9666147, 1.8710723, 1.9005303, 1.9753534, 2.0355756, 2.1005828;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.4378726, 2.2967758, 2.1802788, 2.1628339, 2.2288194, 2.2786529, 2.2584724;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.3656359, 2.3085568, 2.3188434, 2.4140301, 2.513881, 2.5077794;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.206573, 2.20857, 2.3185263, 2.5056028, 2.6312659;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.1686711, 2.1401191, 2.2343175, 2.4260342;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.3495517, 2.2178252, 2.1930335;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.6443374, 2.4216607;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.8480706]
img=
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 2.4431293, 2.1086276, 1.7749974, 1.5721301, 1.5403291, 1.6410155, 1.8406107, 2.1113796, 2.3246853, 2.274801;
0, 0, 0, 0, 0, 0, 0, 0, 2.3276107, 2.0702307, 1.8100098, 1.6615094, 1.6572961, 1.7410251, 1.8701531, 2.0462515, 2.1933937, 2.1447542, 1.8548106;
0, 0, 0, 0, 0, 0, 0, 2.3676813, 2.1666555, 1.9666147, 1.8710723, 1.9005303, 1.9753534, 2.0355756, 2.1005828, 2.1541297, 2.0949042, 1.8804716, 1.6108752;
0, 0, 0, 0, 0, 0, 2.4378726, 2.2967758, 2.1802788, 2.1628339, 2.2288194, 2.2786529, 2.2584724, 2.2164674, 2.1899939, 2.1344388, 2.0028977, 1.8055484, 1.6097167;
0, 0, 0, 0, 0, 2.3656359, 2.3085568, 2.3188434, 2.4140301, 2.513881, 2.5077794, 2.3889487, 2.2654738, 2.21731, 2.2129889, 2.1711345, 2.027447, 1.7903067, 1.5879864;
0, 0, 0, 0, 2.206573, 2.20857, 2.3185263, 2.5056028, 2.6312659, 2.5770819, 2.3866575, 2.2314539, 2.2230167, 2.3092971, 2.3504019, 2.2321868, 1.9485472, 1.637617, 1.494508;
0, 0, 0, 2.1686711, 2.1401191, 2.2343175, 2.4260342, 2.566293, 2.5228219, 2.3388758, 2.2057574, 2.2558136, 2.4211838, 2.5120842, 2.3888607, 2.0588915, 1.6645602, 1.4044838, 1.4204007;
0, 0, 2.3495517, 2.2178252, 2.1930335, 2.3035395, 2.4375367, 2.446404, 2.3236551, 2.2328601, 2.3145993, 2.5046468, 2.5949829, 2.4436085, 2.0789487, 1.6472976, 1.3386253, 1.3225981, 1.6233296;
0, 2.6443374, 2.4216607, 2.271126, 2.2733064, 2.367074, 2.4035037, 2.3307135, 2.2715025, 2.3534446, 2.5142543, 2.558598, 2.3710468, 2.0039113, 1.6069642, 1.3526549, 1.3859948, 1.7268054, 2.1843567;
2.8480706, 2.6081781, 2.4022317, 2.3262172, 2.3576505, 2.3759208, 2.3233094, 2.2885542, 2.3600159, 2.4632583, 2.4390275, 2.2265964, 1.9053584, 1.6181513, 1.4964664, 1.6123655, 1.9332824, 2.2962041, 2.4815767]
And finally using:
warp_mat.at<float>(0,0) = 0; //u11*ratio
warp_mat.at<float>(0,1) = 1; //u22*ratio
warp_mat.at<float>(0,2) = 0+(img.cols >> 1); //lx
warp_mat.at<float>(1,0) = 1; //u21*ratio
warp_mat.at<float>(1,1) = 1; //u22*ratio
warp_mat.at<float>(1,2) = 0+(img.rows >> 1); //ly
I get:
myPatch=
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 2.4431293, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 2.1086276, 2.3276107, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 1.7749974, 2.0702307, 2.3676813, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 1.5721301, 1.8100098, 2.1666555, 2.4378726, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 1.5403291, 1.6615094, 1.9666147, 2.2967758, 2.3656359, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 1.6410155, 1.6572961, 1.8710723, 2.1802788, 2.3085568, 2.206573, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 1.8406107, 1.7410251, 1.9005303, 2.1628339, 2.3188434, 2.20857, 2.1686711, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 2.1113796, 1.8701531, 1.9753534, 2.2288194, 2.4140301, 2.3185263, 2.1401191, 2.3495517, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 2.3246853, 2.0462515, 2.0355756, 2.2786529, 2.513881, 2.5056028, 2.2343175, 2.2178252, 2.6443374, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 2.274801, 2.1933937, 2.1005828, 2.2584724, 2.5077794, 2.6312659, 2.4260342, 2.1930335, 2.4216607, 2.8480706]
img=
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 2.4431293, 2.3276107, 2.3676813, 2.4378726, 2.3656359, 2.206573, 2.1686711, 2.3495517, 2.6443374, 2.8480706;
0, 0, 0, 0, 0, 0, 0, 0, 2.1086276, 2.0702307, 2.1666555, 2.2967758, 2.3085568, 2.20857, 2.1401191, 2.2178252, 2.4216607, 2.6081781, 2.6495261;
0, 0, 0, 0, 0, 0, 0, 1.7749974, 1.8100098, 1.9666147, 2.1802788, 2.3188434, 2.3185263, 2.2343175, 2.1930335, 2.271126, 2.4022317, 2.4685297, 2.4485474;
0, 0, 0, 0, 0, 0, 1.5721301, 1.6615094, 1.8710723, 2.1628339, 2.4140301, 2.5056028, 2.4260342, 2.3035395, 2.2733064, 2.3262172, 2.3705757, 2.3652363, 2.3247712;
0, 0, 0, 0, 0, 1.5403291, 1.6572961, 1.9005303, 2.2288194, 2.513881, 2.6312659, 2.566293, 2.4375367, 2.367074, 2.3576505, 2.3551981, 2.3311026, 2.2715149, 2.1814501;
0, 0, 0, 0, 1.6410155, 1.7410251, 1.9753534, 2.2786529, 2.5077794, 2.5770819, 2.5228219, 2.446404, 2.4035037, 2.3759208, 2.3474753, 2.3124287, 2.240618, 2.1282687, 2.0381868;
0, 0, 0, 1.8406107, 1.8701531, 2.0355756, 2.2584724, 2.3889487, 2.3866575, 2.3388758, 2.3236551, 2.3307135, 2.3233094, 2.3084226, 2.2854021, 2.2117574, 2.088321, 1.9926676, 1.9839712;
0, 0, 2.1113796, 2.0462515, 2.1005828, 2.2164674, 2.2654738, 2.2314539, 2.2057574, 2.2328601, 2.2715025, 2.2885542, 2.2938819, 2.2722201, 2.1820612, 2.0477793, 1.957217, 1.954851, 2.0058911;
0, 2.3246853, 2.1933937, 2.1541297, 2.1899939, 2.21731, 2.2230167, 2.2558136, 2.3145993, 2.3534446, 2.3600159, 2.3450513, 2.2874477, 2.1686828, 2.0435023, 1.9943975, 2.0270162, 2.0777535, 2.1049571;
2.274801, 2.1447542, 2.0949042, 2.1344388, 2.2129889, 2.3092971, 2.4211838, 2.5046468, 2.5142543, 2.4632583, 2.3841665, 2.2811179, 2.1669631, 2.1026075, 2.1358697, 2.2212756, 2.2625117, 2.2268343, 2.180846]
I think you basically answered yourself and it looks like a basic affine transformation.
The equivelent in OpenCV is warpAffine.
In the flags of the function you can give it any of the InterpolationFlags.
The transformation matrix M at your case will be:
[[a11, a12, ofsx],
[a21, a22, ofsy]
The output size is also a parameter, dependes on your numbers.
And if you want to optimize it as you say, you can compile OpenCV with CUDA support and then you could use the GPU version of this function.

Count number of multiples against every power of 4

Given a number, n, I need to efficiently find how many times this number is a multiple of all powers of 4 less than the given number.
For examples:
16 is a multiple of 4, and 16, so the result would be 2.
64 is a multiple of 4, 16, and 64, so the result would be 3.
256 is a multiple of 4, 16, 64, and 256, so the result would be 4.
14 is not a multiple of any power of 4, so the result would be 0.
35 is not a multiple of any power of 4, so the result would be 0.
Bitwise operations are preferred, and this is in a very tight loop so it is inside of a bottleneck that needs to be efficient. My code at the moment is the obvious answer, but I have to believe there is something more mathematical that can figure out the result in less steps:
power = 4;
while (power < n) {
result += !(n & (power - 1));
power *= 4;
}
You could use logarithms. A quick Google search for "fast log2 c++" brought up a pretty long list of ideas. Then your answer is log2(x)/2, and you'd have to find some way to make sure that your result is a whole number if you only want an answer for exact powers of 4.
If you are programming for an x86 processor, you can use BitScanForward & BitScanReverse to find the set bit, and use it to compute log2. The following code works in Visual Studio, for GCC or others, there are other ways to do inline assembly.
uint32_t exact_power_of_4_scan(uint32_t num)
{
unsigned long reverse;
unsigned long forward;
if (!_BitScanReverse(&reverse, num)) return 0;
_BitScanForward(&forward, num);
if (reverse != forward) return 0; // makes sure only a single bit is set
if (reverse & 0x1) return 0; // only want every other power of 2
return reverse / 2;
}
If you need a portable solution, table lookup might be the way to go, but is more complicated.
uint8_t not_single_bit[256] = {
1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
uint8_t log2_table[256] = {
0, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
uint32_t exact_power_of_2(uint32_t num)
{
auto a = not_single_bit[num & 0xff];
auto b = not_single_bit[(num >> 8) & 0xff];
auto c = not_single_bit[(num >> 16) & 0xff];
auto d = not_single_bit[(num >> 24) & 0xff];
if (a + b + c + d != 3) {
return 0;
}
if (!a) {
return log2_table[num & 0xff];
}
if (!b) {
return log2_table[(num >> 8) & 0xff] + 8;
}
if (!c) {
return log2_table[(num >> 16) & 0xff] + 16;
}
return log2_table[(num >> 24) & 0xff] + 24;
}
uint32_t exact_power_of_4(uint32_t num)
{
auto ret = exact_power_of_2(num);
if (ret & 0x1) return 0;
return ret / 2;
}
Both are linear algorithms. The first will probably beat out looping for almost any value of num, but I haven't tested it. The second is probably only good for largish nums.
The mathematics would be to keep dividing by 4 until the result is no longer divisible by 4.
If you really want to do it with bitwise operations, techniques here can be used to count the number of trailing zero bits (i.e. the number of times a value is divisible by 2). Those can be adjusted to count pairs of trailing bits (i.e. divisibility by a power of 4 rather than 2).
Note that you will need to work with unsigned values to avoid certain cases of undefined or unspecified behaviours.
I would dispute your assertion that bitwise operations will make for a more efficient solution. It is not a given without testing, particularly with modern compilers.

Opencv Matrix Range L value : Is this a bug?

It seems to me that using Matrix with Ranges as an L-value (assignment target) should work or not (and if not a compiler error would be nice) but not both depending on the particulars of a legitimate r-value.
cout << "hi mom" << endl;
Mat Img0=Mat::zeros(7,7,CV_8UC1);
Mat Img1=Mat::ones(7,7,CV_8UC1);
cout << Img0 << endl;
cout << Img1 << endl;
Img0(Range::all(), Range::all()) = Img1;
cout << Img0 << endl;
Img0(Range::all(), Range::all()) = 1;
cout << Img0 << endl;
Below is the output from the above. The first two matrix print outs are of Img0 and Img1 as initialized by Mat::zeros and Mat::ones respectively.
The third matrix print out is Img0 again but after
Img0(Range::all(), Range::all()) = Img1;
which I expected would set Img0 to Img1; i.e. all ones; but it's not. It's still all zeros.
The fourth/last matrix print out is the result of
Img0(Range::all(), Range::all()) = 1;
Which has the same L value as the third assignment but it works when a scalar is the Rvalue (unlike the third which as a matrix as the RValue).
Is there some sense in this that I'm missing? Should this r-value distinction behavior be allowed? It seems inconsistent to me.
[0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0]
[1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1]
[0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0]
[1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1]
No, this is not a bug.
This line Img0(Range::all(), Range::all()) = Img1; doesn't work as expected because Img0(Range::all(), Range::all()) forms a temporary header that is further assigned to another header, which is Img1. Remember that each of these operations is O(1), that is, no data is copied. Thus, no real assignment happens.
You can realize this effect more clearly by doing this:
(Img0(Range::all(), Range::all()) = Img1) = 2;
cout << Img0 << endl;
cout << Img1 << endl;
If you have understood what I described above, you should be aware of that the code will only change the value of Img1. And the output is:
[0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0]
[2, 2, 2, 2, 2, 2, 2;
2, 2, 2, 2, 2, 2, 2;
2, 2, 2, 2, 2, 2, 2;
2, 2, 2, 2, 2, 2, 2;
2, 2, 2, 2, 2, 2, 2;
2, 2, 2, 2, 2, 2, 2;
2, 2, 2, 2, 2, 2, 2]
Further reading: check out similar effect happened to Mat::row().

Translating array pointer access from C++ to Delphi

I'd like to know if I translated a piece of code correctly from C++ to Delphi.
It looks like it is working, but I have a feeling that I'm reading and writing into memory that I'm not supposed to using Delphi.
Given C++ code:
struct tile_map
{
int32 CountX;
int32 CountY;
uint32 *Tiles;
};
inline uint32
GetTileValueUnchecked(tile_map *TileMap, int32 TileX, int32 TileY)
{
uint32 TileMapValue = TileMap->Tiles[TileY*TileMap->CountX + TileX];
return(TileMapValue);
}
uint32 Tiles00[9][17] =
{
{1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
};
// More tile map declarations ...
// uint32 Tiles01[9][17] = ...
// uint32 Tiles10[9][17] = ...
// uint32 Tiles11[9][17] = ...
tile_map TileMaps[2][2];
TileMaps[0][0].CountX = 17;
TileMaps[0][0].CountY = 9;
TileMaps[0][0].Tiles = (uint32 *)Tiles00;
TileMaps[0][1] = TileMaps[0][0];
TileMaps[0][1].Tiles = (uint32 *)Tiles01;
TileMaps[1][0] = TileMaps[0][0];
TileMaps[1][0].Tiles = (uint32 *)Tiles10;
TileMaps[1][1] = TileMaps[0][0];
TileMaps[1][1].Tiles = (uint32 *)Tiles11;
// Usage
int32 PlayerTileX = 2;
int32 PlayerTileY = 2;
uint32 TileMapValue = GetTileValueUnchecked(&TileMap[1][1], PlayerTileX, PlayerTileY);
Delphi translation:
program Project1;
{$APPTYPE CONSOLE}
type
Puint32 = ^uint32;
tile_map = record
CountX : int32;
CountY : int32;
Tiles : Puint32;
end;
Ptile_map = ^tile_map;
{$POINTERMATH ON}
function GetTileValueUnchecked(TileMap : Ptile_map; TileX, TileY : int32) : uint32; inline;
begin
result := TileMap^.Tiles[TileY * TileMap^.CountX + TileX];
end;
const //in the future these will be read from file, so const for now
Tiles00: array [0..8, 0..16] of uint32 =
(
(1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1),
(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1),
(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1),
(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1),
(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1),
(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1),
(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1),
(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
);
// More tile map declarations ...
//Tiles01: array [0..8, 0..16] of uint32 = ...
//Tiles10: array [0..8, 0..16] of uint32 = ...
//Tiles11: array [0..8, 0..16] of uint32 = ...
var
TileMaps : array [0..1, 0..1] of tile_map;
PlayerTileX, PlayerTileY : int32;
TileMapValue : uint32;
begin
TileMaps[0][0].CountX := 17;
TileMaps[0][0].CountY := 9;
TileMaps[0][0].Tiles := Addr(Tiles00);
TileMaps[0][1] := TileMaps[0][0];
TileMaps[0][1].Tiles := Addr(Tiles01);
TileMaps[1][0] := TileMaps[0][0];
TileMaps[1][0].Tiles := Addr(Tiles10);
TileMaps[1][1] := TileMaps[0][0];
TileMaps[1][1].Tiles := Addr(Tiles11);
// Usage
PlayerTileX := 2;
PlayerTileY := 2;
TileMapValue = GetTileValueUnchecked(#TileMaps[1][1], PlayerTileX, PlayerTileY);
end.
David Heffernan's comments has been helpful and others seem to agree that the code is correct, so I will mark this as answered.

How does the Python’s * operator work? [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 9 years ago.
I use the python's * to create a 2-dimetion list [[0]*10]*10 with a default value 0.
But when I set the first element to 1,all the elements of the first colum happend to be 1,why?
This does not happen when I create the list using append(see below variable data ).
#!/bin/env python
#encoding=utf8
width = 10
height = 10
data = []
for i in xrange(width):
data.append([0 for j in xrange(height)])
data2 = [[0]*width]*height
print "before:",data == data2
data[0][0] = 1
data2[0][0] = 1
print "after:",data == data2
print "actually:"
print data
print data2
output:
before: True
after: False
actually:
[[1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
[[1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
The * operator on a list will repeat the objects in the list. But it doesn't make copies of the objects, it repeats the actual objects themselves.
The distinction is subtle, and many times you won't notice it. If the objects are immutable such as numbers or strings, all you can do is replace the object with a different object, and then the members of the list will no longer be the same object.
When the objects in the list can be modified, such as another list, any modification to that object is reflected in all the other repeated references in the list.
There's an awkward workaround:
data3 = [[0]*width for i in range(height)]
Here:
[[0]*width]
you only create a single list [0], and then you create another list containing width references to that single object. The key point is that the * operator only evaluates its operands once.
Here:
for i in xrange(width):
data.append([0 for j in xrange(height)])
you are creating a new list on each iteration that you then append.