directcompute hlsl numthreads? - hlsl

Since you already define the thread groups to be executed when dispaching a compute shader, what do the numbers inside the shader file signify? example: [numthreads(1, 1, 1)]

Did some more digging, by official definition when dispatching you define thread groups while the numthreads statement defines the threads so basically they can be taken as extra dimensions. For example when i dispatch 2,2,1 to a function with 3,1,1 it spawns
enter code here
0, 0, 0 - 0, 0, 0
0, 0, 0 - 1, 0, 0
0, 0, 0 - 2, 0, 0
1, 0, 0 - 0, 0, 0
1, 0, 0 - 1, 0, 0
1, 0, 0 - 2, 0, 0
0, 1, 0 - 0, 0, 0
0, 1, 0 - 1, 0, 0
0, 1, 0 - 2, 0, 0
1, 1, 0 - 0, 0, 0
1, 1, 0 - 1, 0, 0
1, 1, 0 - 2, 0, 0
so 2*2*1*3*1*1 = 12 threads total

Related

How do I create multiple levels in pygame?

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.

how to print 2-D array row by row in GDB?

map[22][22];
I want to see 'map(2-D array)' by GDB and the result was like this
$1 = {{-1 repeats 22 times}, {-1, 4, 4, 4, 4, 2, 3, 2, 1, 0, 4, -1 repeats 11 times}, {-1, 1, 1, 2, 2, 5, 2, 0, 0, 0, 2, -1 repeats 11 times}, {-1, 3, 0, 0, 1, 1, 1, 0, 0, 0, 0, -1 repeats 11 times}, {-1, 1, 0, 0, 0, 0, 0, -1, 4, 4, 1, -1 repeats 11 times}, {-1, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, -1 repeats 11 times}, {-1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1 repeats 11 times}, {-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1 repeats 11 times}, {-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1 repeats 11 times}, {-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1 repeats 11 times}, {-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1 repeats 11 times>}, {-1 repeats 22 times} repeats 11 times>}
and it was so unuseful to see..
I want to see like this
{-1,-1,-1,-1,-1,-1,-1,1}
{1,2,3,4,5,2,4,}
{2,1,4,5,3,4,2,2}
...
can you tell how to print 2-D array row by row??
I want to see like this
There are 2 ways to achieve this:
Implement debug_print() function in your program, call it from GDB with the call command.
Implement Python pretty-printer. Documentation. Tutorial.
The first solution is trivial to implement, but (unlike the second) doesn't work when you don't have a live process (e.g. for core postmortem debugging).

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.

Array consisting of the values inside of another array

If I have an array that looks like this:
int map[21][28] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 1, 0, 0, 0, 0, 0, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
How can I create a smaller array consisting of the values inside that array..?
A bit like this:
int zoomedMap[7][7] =
{
2, 2, 1, 1, 1, 1, 1,
1, 0, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 1, 1, 1
};
I don't know if this helps, but:
I know the exact dimensions of both arrays
I want it to be possible to move the smaller arrays position, preferably by just changing an X/Y value
In what is hopefully obvious, your sub-array is literally nothing more than a "block" of data (with some interesting partitioning) within your main array. Assuming you are checking your boundaries and will NOT allow an out of bounds condition to happen, you can simulate your sub-array using pointer math and some basic info about your main array.
The block will always be some [row][column] offset from the [0][0] location, so we need those values (row and column).
The block has fixed width such that column+width does not exceed your main array width. We need that width.
The block has fixed height such that row+height does not exceed your main array height. We need that height.
I hope it obvious we need the base address that is the main array (in your case map).
This is probably best demonstrated by example. The following is NOT some end-all solution. It will likely not even address 1/10th of the need you're going to have. Rather, it is intended to offer you an idea on how you can do this using only a pointer, some offsets, some sizes, and a little arithmetic to get what you're looking for. There is nothing stopping you from exceeding limits that may be harmful (just like a plain array), so be cautious.
// internal rerefential to a submatrix in a larger fixed matrix.
template<typename T>
class Sub2D
{
public:
template<size_t R, size_t C>
Sub2D(T(&ar)[R][C], int top, int left, int height, int width)
: parent(ar[0])
, row(top)
, col(left)
, max_row(R)
, max_col(C)
{
if ((row+width) >= R || (col+height) >= C)
throw std::out_of_range("");
}
// retrieve our subrow offset into the main 2D array
T* operator [](size_t n)
{
// enable at your desire, but as Alex pointed out, all
// the standard containers let you shoot yourself in the
// foot with this operator. why not this one too =P
//if (row+n >= max_row)
// throw std::out_of_range("");
return parent + ((row+n)*max_col + col);
}
private:
T* parent;
size_t row, col;
size_t max_row, max_col;
};
Used like this, assuming your array in your question is the one we're basing:
int main()
{
// take the submatrix & [6][7] that is 7x7 in dimension.
Sub2D<int> sub(map, 6,7, 7,7);
for (size_t i=0;i<7;++i)
{
for (size_t j=0;j<7;++j)
cout << sub[i][j] << ' ';
cout << endl;
}
cout << endl;
// update an element at location [1][1] of our sub-matrix.
sub[1][1] = 9;
// reprint the *entire* main array. it better have updated.
for (size_t i=0;i<sizeof(map)/sizeof(map[0]);++i)
{
for (size_t j=0;j<sizeof(map[0])/sizeof(map[0][0]);++j)
cout << map[i][j] << ' ';
cout << endl;
}
cout << endl;
return 0;
}
Produces the following output.
2 2 1 1 1 1 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 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 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 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 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 1 9 0 0 0 0 1 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 1 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 1 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 1 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 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Note the 9 now sitting right where we expect it.
There is obviously a LOT more you can add to such a template class, including better range checking, moving your pointer, snap-shotting into other memory buffers, etc, but the point is for basic get-me-this sub matrix a pointer and a few offsets are hard to beat, especially for performance.
You could always do it statically with loops:
const int pos_x = 6, pos_y = 7, size_x = 7, size_y = 7;
int newMap[size_x][size_y] = {0};
for( int i = pos_x; i != pos_x+size_x; ++i ) {
for( int j = pos_y; j != pos_y+size_y; ++j) {
newMap[i-pos_x][j-pos_y] = map[i][j];
}
}
Although this isn't very safe, and difficult to get working dynamically.
You might want to either write a matrix-wrapper class with the functions you desire; or find one that already exists and extend it (I'd start looking into the STL or Boost for an existing matrix class)
Have a read of Boost's uBLAS module. It provides Matrix and MatrixRange classes, which are exactly what you are looking for.
In essence, the zoomedMap should just be an intelligent pointer into the larger matrix, which understands how to dereference and get the correct result.
Depending on your requirements, this may suffice:
int (*zoomedMap)[28] = reinterpret_cast<int (*)[28]>(&map[X][Y]);
This gives you an identifier you can use as if it were a two-dimensional array: zoomedMap[i][j]. You can easily move the zoomed map within the larger array by assigning a new address to it.
It depends on your C++ implementation allowing a pointer to float to be cast to a pointer to an array of float, provided all references remain within the original array. This is common.
It leaves zoomedMap pointing to the same memory as map. Thus, you cannot change one without changing the other. If you want to do that, you would need to make a copy.

How to scale down blocks without causing pixel overlapping

I have a bunch of blocks that needs to be drawn into a grid. Now displaying them unscaled everything is fine but when I try to scale them down to fit withing a window I get "scale-artifacts" because I use a normal scale-ratio formula and floats.
Is there a way to avoid these problems ?
Common example data:
Original length: 200000
Scaled down to a 25x25 pixel grid (it's this small for development and debugging)
The scaled down max length: 625 (25 * 25)
Scale-ratio: (625 / 200000) = 0,003125
Example data 1 - overlapping, scaled blocks overwrite each other
Start of block => end of block: [start, end)
1: 2100 => 2800
2: 2800 => 3600
3: 3600 => 4500
4: 4500 => 5500
Jumping over showing the output of this example because I think example 2 and 3 will get the point across. Left it in for completeness.
Example data 2 - incorrect space between 2 and 3
Start of block => end of block: [start, end)
1: 960 => 1440
2: 1440 => 1920
3: 1920 => 2400
1: 960 => 1440, length: 480, scaled length: 1.5:
2: 1440 => 1920, length: 480, scaled length: 1.5:
3: 1920 => 2400, length: 480, scaled length: 1.5:
pixel start, end, length
1: 3, 0, 1
2: 4, 0, 1
3: 6, 0, 1
Displayed grid:
[ 0, 0, 0, 1, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
...
Example data 3 - 1 moved a step back incorrectly
Start of block => end of block: [start, end)
1: 896 => 1344
2: 1344 => 1792
3: 1792 => 2240
1: 896 => 1344, length: 448, scaled length: 1.4:
2: 1344 => 1792, length: 448, scaled length: 1.4:
3: 1792 => 2240, length: 448, scaled length: 1.4:
pixel start, end, length
1: 2, 0, 1
2: 4, 0, 1
3: 5, 0, 1
Displayed grid:
[ 0, 0, 1, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
...
What example data 2 and 3 should have looked like:
[ 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
...
Remember the block values are [start, end)
Preemptive strike (down-voters / trollers) Remember: I'm not psychic or a mind-reader. If you want to give negative do it in a constrictive way or it is useless (i will not learn anything) and will just pollute the thread.
Update
#include <iostream>
#include <math.h>
#include <limits.h>
#include <assert.h>
#include <vector>
#include <array>
#include <utility> // pair
#include <algorithm> // for_each
using namespace std;
const size_t width_size = 25; // 25 pixels
const size_t height_size = 25; // 25 pixels
const size_t grid_length = width_size * height_size; // width * height
array<size_t, grid_length> grid;
const size_t original_length = 200000;
typedef pair<unsigned long, unsigned long> block;
vector<block> test_values;
void show_grid()
{
for (size_t y = 0; y < height_size; ++y) {
const size_t start_pos_for_current_heigth = y * width_size;
const size_t end_pos_for_current_heigth = start_pos_for_current_heigth + width_size;
cout << "[ ";
for (size_t i = start_pos_for_current_heigth; i < end_pos_for_current_heigth; ++i) {
if (i + 1 < end_pos_for_current_heigth)
cout << grid[i] << ", ";
else
cout << grid[i];
};
cout << " ]" << endl;
}
}
void scale_and_add(const float scale)
{
size_t test_value_id = 1;
for_each(test_values.cbegin(), test_values.cend(), [&](const block &p) {
const float s_f = p.first * scale;
const unsigned long s = round(s_f);
const float e_f = p.second * scale;
const unsigned long e = round(e_f);
const unsigned long block_length = p.second - p.first;
const float block_length_scaled = block_length * scale;
assert(s <= grid_length);
assert(e <= grid_length);
cout << test_value_id << ":" << endl;
cout << " " << p.first << " => " << p.second << " length: " << block_length << endl;
cout << " " << s << " (" << s_f << ") => " << e << " (" << e_f << ") length: " << (e - s) << " (" << block_length_scaled << ")" << " (scaled)" << endl;
for (size_t i = s; i < e; ++i) {
if (grid[i] != 0) {
cout << "overlapp detected !" << endl;
}
grid[i] = test_value_id;
}
++test_value_id;
});
}
void reset_common()
{
grid.fill(0);
test_values.clear();
}
int main()
{
const float scale = ((float)grid_length / (float)original_length);
cout << "scale: " << scale << " length per pixel: " << ((float)original_length / (float)grid_length) << endl;
// Example data 1
/* cout << "Example data 1" << endl;
test_values.push_back(make_pair(2100, 2800));
test_values.push_back(make_pair(2800, 3600));
test_values.push_back(make_pair(3600, 4500));
test_values.push_back(make_pair(4500, 5500));
scale_and_add(scale);
show_grid();
reset_common();
// Example data 2
cout << "Example data 2" << endl;
test_values.push_back(make_pair(960, 1440));
test_values.push_back(make_pair(1440, 1920));
test_values.push_back(make_pair(1920, 2400));
scale_and_add(scale);
show_grid();
reset_common();
// Example data 3
cout << endl << "Example data 3" << endl;
test_values.push_back(make_pair(896, 1344));
test_values.push_back(make_pair(1344, 1792));
test_values.push_back(make_pair(1792, 2240));
scale_and_add(scale);
show_grid();
reset_common();*/
// Generated data - to quickly find the problem
cout << "Generated data" << endl;
auto to_op = [&](const size_t v) {
return v * (original_length / grid_length) * 1.3; // 1.4 and 1.5 are also good values to show the problem
};
size_t pos = 0;
size_t psize = 1; // Note this value (length) and check it with the displayed one, you'll be surprised !
for (size_t g = 0; g < 10; ++g) {
test_values.push_back(make_pair(to_op(pos), to_op(pos + psize)));
pos += psize;
}
scale_and_add(scale);
show_grid();
return 0;
}
Output:
scale: 0.003125 length per pixel: 320
Generated data
1:
0 => 416 length: 416
0 (0) => 1 (1.3) length: 1 (1.3) (scaled)
2:
416 => 832 length: 416
1 (1.3) => 3 (2.6) length: 2 (1.3) (scaled)
3:
832 => 1248 length: 416
3 (2.6) => 4 (3.9) length: 1 (1.3) (scaled)
4:
1248 => 1664 length: 416
4 (3.9) => 5 (5.2) length: 1 (1.3) (scaled)
5:
1664 => 2080 length: 416
5 (5.2) => 7 (6.5) length: 2 (1.3) (scaled)
6:
2080 => 2496 length: 416
7 (6.5) => 8 (7.8) length: 1 (1.3) (scaled)
7:
2496 => 2912 length: 416
8 (7.8) => 9 (9.1) length: 1 (1.3) (scaled)
8:
2912 => 3328 length: 416
9 (9.1) => 10 (10.4) length: 1 (1.3) (scaled)
9:
3328 => 3744 length: 416
10 (10.4) => 12 (11.7) length: 2 (1.3) (scaled)
10:
3744 => 4160 length: 416
12 (11.7) => 13 (13) length: 1 (1.3) (scaled)
[ 1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
This code example demonstrates my problem more clearly.
Interesting fact: mingw-g++, which i used to write this example, shows slightly different values. I usually use visual studio 2010 but couldn't this time because I'm not at home.
I am not sure if I am getting the problem statement but I will take a stab at it. You have ranges of information that you are displaying contigously a range is usually [a,b). Everything is fine when a and b directly represent the pixels that you are trying to draw, but you are having problems when you want to scale the whole thing.
Not dealing with multiple rows of pixels, if you have two ranges R1=[a,b) and R2=[b,c) unscaled you just draw from a to b-1 and from b to c-1 and your ranges are drawn so what is the problem in the scaled case drawing from (int)(a*scale) to ((int)(b*scale)-1) and then from (int)(b*scale) to ((int)(c*scale)-1), you can use any float to int conversion, rounding, floor or ceiling and you should be ok.
The next problem area would be if your scale ranges amount to less than 1 pixel, in this case you might need to detect if the size of the scaled range is 0 and carry a correction factor (in pixels) that is added at the end of the calculation.
Pseudocode
DrawRanges(List<Range> ranges, float scale)
int carry = 0;
foreach(Range range in ranges)
{
int newStart = ceiling(range.start*scale);
int newEnd = ceiling(range.end*scale)-1;
if (newStart <= newEnd)
{
newEnd = newStart;
++carry;
}
DrawRange(newStart+carry,newEnd+carry);
}
This will eventually fail if you have more Ranges than blocks in your scaled down grid, you would have to figure out how to drop ranges completely. In draw rang you map your index to an actual block coordinate.
Does this solve your problem ?
Yeah +1 to get you back up, the question is OK.
I don't know why people thing it is so fun to downvote without even leaving a comment.
Well, to the question :-)
Usually when drawing you have this overlapping issues and in 3D computer graphics with scanline renderers (DirectX & OpenGL for ex) they usually Skip exactly one pixel (say all on the right and down side).
Maybe this can help you out.
It is possible too that when the division is perfect, you don't have the artefacts so you must maybe deal with that (ie. if the value is a 'perfect integer', for example 185.000000 then don't remove the last pixel).
HTH