def check_for_customer_by_polarity(self, is_hero): # Customer presence is determined in two phases. First # the average price for that customer type is computed. # The average price allure is then computed. # 1 customer appears every 20 seconds on average. # At 30 fps, this is 1 / 600, when all prices are $100. # The allure ratio is multiplied to the denominator and creates # a value X. # If random.random() is less than X, a customer is created. x = 1.0 / (NORMAL_CUSTOMER_FREQUENCY * 30) p = ('h', 'n') if is_hero else ('v', 'n') # polarities relevant colors = ALL_COLORS[:self.spectrum_available] total_price = 0 average_price = 0 for color in colors: for polarity in p: average_price += 100 total_price += self.prices[polarity + '_' + color] allure = 1.0 * average_price / total_price x *= allure if random.random() > x: return None character_key = random.choice(HEROES if is_hero else VILLAINS) # 2 colors or less: 1 demand # 5 colors or less: 1 or 2 demands # 8 colors or less: 1 to 3 demands # 9 or more colors: 2 to 4 demands lc = len(colors) if lc < 3: num_demands = [1] elif lc < 6: num_demands = [1, 2] elif lc < 9: num_demands = [1, 2, 3] else: num_demands = [2, 3, 4] num_demands = random.choice(num_demands) demands = self.get_demands(num_demands, is_hero) sprite = Sprite(character_key, is_hero, demands) return sprite
def __init__(self): self.next = self self.session = Session() self.player = Sprite('player') self.player = Sprite('player') self.sprites = [self.player] self.last_color = None self.sprites_by_row = None self.lifetime = 0 # Forgive me father for I am about to sin. m = [ 'xx xx xx xx xx xx xx xx c7 c8 c8 c8 c8 c8 c8 c8 c8 c8 c9 xx xx xx xx xx xx xx xx', 'c7 c8 c8 c8 c8 c8 c9 xx c4 c5 c5 c5 c5 c5 c5 c5 c5 c5 c6 xx c7 c8 c8 c8 c8 c8 c9', 'c4 c5 c5 c5 c5 c5 c6 xx c4 f7 f8 f8 f8 f8 f8 f8 f8 f9 c6 xx c4 c5 c5 c5 c5 c5 c6', 'c4 f7 f8 f8 f8 f9 C1 c8 C3 f4 f5 f5 f5 f5 f5 f5 f5 f6 C1 c8 C3 f7 f8 f8 f8 f9 c6', 'c4 f4 f5 f5 f5 f6 c5 c5 c5 f4 f5 f5 f5 f5 f5 f5 f5 f6 c5 c5 c5 f4 f5 f5 f5 f6 c6', 'c4 f4 f5 f5 f5 F1 f8 f8 f8 F3 f5 f5 f5 f5 f5 f5 f5 F1 f8 f8 f8 F3 f5 f5 f5 f6 c6', 'c4 f4 f5 f5 f5 F7 f2 f2 f2 F9 f5 f5 f5 f5 f5 f5 f5 F7 f2 f2 f2 F9 f5 f5 f5 f6 c6', 'c4 f4 f5 f5 f5 f6 C7 c2 C9 f4 f5 f5 f5 f5 f5 f5 f5 f6 C7 c2 C9 f4 f5 f5 f5 f6 c6', 'c4 tl ct ct ct tr c6 xx c4 f4 f5 f5 f5 f5 f5 f5 f5 f6 c6 xx c4 tl ct ct ct tr c6', 'c4 bl cb cb cb br c6 xx c4 f4 f5 f5 f5 f5 f5 f5 f5 f6 c6 xx c4 bl cb cb cb br c6', 'c4 f4 f5 f5 f5 f6 c6 xx c4 f4 f5 f5 f5 f5 f5 f5 f5 f6 c6 xx c4 f4 f5 f5 f5 f6 c6', 'c4 f4 f5 f5 f5 f6 c6 xx c4 f4 f5 f5 f5 f5 f5 f5 f5 f6 c6 xx c4 f4 f5 f5 f5 f6 c6', 'c4 f4 f5 f5 f5 f6 c6 xx c4 f4 f5 f5 f5 f5 f5 f5 f5 f6 c6 xx c4 f4 f5 f5 f5 f6 c6', 'c4 f1 f2 f5 f2 f3 c6 xx c4 f1 f2 f2 f2 f2 f2 f2 f2 f3 c6 xx c4 f1 f2 f5 f2 f3 c6', 'c1 c2 c2 dd c2 c2 c3 xx c1 c2 c2 c2 c2 c2 c2 c2 c2 c2 c3 xx c1 c2 c2 dd c2 c2 c3' ] # Transpose this cols = [] row_count = len(m) col_count = len(m[0].split()) for i in range(len(m)): m[i] = m[i].split() x = 0 while x < col_count: col = [] y = 0 while y < row_count: col.append(Tile(m[y][x])) y += 1 x += 1 cols.append(col) self.grid = cols for i in range(5): v = self.grid[1 + i][8] h = self.grid[21 + i][8] v.is_counter = True h.is_counter = True v.counter_slot = i h.counter_slot = i v.counter_is_hero = False h.counter_is_hero = True self.player.x = 14.5 self.player.y = 12.5 #self.set_up_boxes(10) self.session.order_more('red', True)
class PlayScene: def __init__(self): self.next = self self.session = Session() self.player = Sprite('player') self.player = Sprite('player') self.sprites = [self.player] self.last_color = None self.sprites_by_row = None self.lifetime = 0 # Forgive me father for I am about to sin. m = [ 'xx xx xx xx xx xx xx xx c7 c8 c8 c8 c8 c8 c8 c8 c8 c8 c9 xx xx xx xx xx xx xx xx', 'c7 c8 c8 c8 c8 c8 c9 xx c4 c5 c5 c5 c5 c5 c5 c5 c5 c5 c6 xx c7 c8 c8 c8 c8 c8 c9', 'c4 c5 c5 c5 c5 c5 c6 xx c4 f7 f8 f8 f8 f8 f8 f8 f8 f9 c6 xx c4 c5 c5 c5 c5 c5 c6', 'c4 f7 f8 f8 f8 f9 C1 c8 C3 f4 f5 f5 f5 f5 f5 f5 f5 f6 C1 c8 C3 f7 f8 f8 f8 f9 c6', 'c4 f4 f5 f5 f5 f6 c5 c5 c5 f4 f5 f5 f5 f5 f5 f5 f5 f6 c5 c5 c5 f4 f5 f5 f5 f6 c6', 'c4 f4 f5 f5 f5 F1 f8 f8 f8 F3 f5 f5 f5 f5 f5 f5 f5 F1 f8 f8 f8 F3 f5 f5 f5 f6 c6', 'c4 f4 f5 f5 f5 F7 f2 f2 f2 F9 f5 f5 f5 f5 f5 f5 f5 F7 f2 f2 f2 F9 f5 f5 f5 f6 c6', 'c4 f4 f5 f5 f5 f6 C7 c2 C9 f4 f5 f5 f5 f5 f5 f5 f5 f6 C7 c2 C9 f4 f5 f5 f5 f6 c6', 'c4 tl ct ct ct tr c6 xx c4 f4 f5 f5 f5 f5 f5 f5 f5 f6 c6 xx c4 tl ct ct ct tr c6', 'c4 bl cb cb cb br c6 xx c4 f4 f5 f5 f5 f5 f5 f5 f5 f6 c6 xx c4 bl cb cb cb br c6', 'c4 f4 f5 f5 f5 f6 c6 xx c4 f4 f5 f5 f5 f5 f5 f5 f5 f6 c6 xx c4 f4 f5 f5 f5 f6 c6', 'c4 f4 f5 f5 f5 f6 c6 xx c4 f4 f5 f5 f5 f5 f5 f5 f5 f6 c6 xx c4 f4 f5 f5 f5 f6 c6', 'c4 f4 f5 f5 f5 f6 c6 xx c4 f4 f5 f5 f5 f5 f5 f5 f5 f6 c6 xx c4 f4 f5 f5 f5 f6 c6', 'c4 f1 f2 f5 f2 f3 c6 xx c4 f1 f2 f2 f2 f2 f2 f2 f2 f3 c6 xx c4 f1 f2 f5 f2 f3 c6', 'c1 c2 c2 dd c2 c2 c3 xx c1 c2 c2 c2 c2 c2 c2 c2 c2 c2 c3 xx c1 c2 c2 dd c2 c2 c3' ] # Transpose this cols = [] row_count = len(m) col_count = len(m[0].split()) for i in range(len(m)): m[i] = m[i].split() x = 0 while x < col_count: col = [] y = 0 while y < row_count: col.append(Tile(m[y][x])) y += 1 x += 1 cols.append(col) self.grid = cols for i in range(5): v = self.grid[1 + i][8] h = self.grid[21 + i][8] v.is_counter = True h.is_counter = True v.counter_slot = i h.counter_slot = i v.counter_is_hero = False h.counter_is_hero = True self.player.x = 14.5 self.player.y = 12.5 #self.set_up_boxes(10) self.session.order_more('red', True) def place_box(self, key): storage_left = 11 storage_width = 5 storage_top = 2 storage_height = 5 box = Box(key) while True: x = storage_left + int(random.random() * storage_width) y = storage_top + int(random.random() * storage_height) dx = abs(x - self.player.x) dy = abs(y - self.player.y) if dx > 2 or dy > 2: break tile = self.grid[x][y] if tile.stack == None: tile.stack = [] tile.stack.append(box) def create_random_boxes(self, count): storage_left = 11 storage_width = 5 storage_top = 2 storage_height = 5 output = [] for i in range(count): box = self.session.get_random_box(True) x = int(random.random() * storage_width) + storage_left y = int(random.random() * storage_height) + storage_top output.append([box, x, y]) return output def set_up_boxes(self, count): boxes = self.create_random_boxes(count) for box in boxes: b = box[0] x = box[1] y = box[2] tile = self.grid[x][y] if tile.stack == None: tile.stack = [] tile.stack.append(b) def incorrect_order(self): play_sound("incorrect_order") pass def lift(self, is_full): dxdy = _direction_to_vector[self.player.direction] x = int(self.player.x) + dxdy[0] y = int(self.player.y) + dxdy[1] tile = self.grid[x][y] if self.player.holding == None: if tile.stack != None and not tile.is_counter: if is_full: self.player.holding = tile.stack tile.stack = None else: self.player.holding = [tile.stack[-1]] if len(tile.stack) == 1: tile.stack = None else: tile.stack = tile.stack[:-1] play_sound('lift') else: fix_loc = False if not tile.passable and not tile.is_counter: play_sound('cant_drop_box') return to_drop = [] if is_full: to_drop = self.player.holding[:] else: to_drop = self.player.holding[:1] item_sold = False if tile.is_counter: for sprite in self.sprites: if sprite.phase == 4: if sprite.counter_slot == tile.counter_slot: if sprite.is_hero == tile.counter_is_hero: sprite_demands = sprite.demands[:] for item_to_drop in to_drop: found = False i = 0 while i < len(sprite_demands): d = sprite_demands[i] if d == item_to_drop.key: found = True sprite_demands = sprite_demands[:i] + sprite_demands[i + 1:] break i += 1 if not found: self.incorrect_order() return self.session.item_sold(sprite, item_to_drop.key) item_sold = True break if item_sold: play_sound('money_sound') elif tile.is_counter: # can't drop a box on a counter without selling it return else: play_sound('drop') if tile.stack == None: fix_loc = True tile.stack = [] if is_full: for item in self.player.holding: tile.stack.append(item) self.player.holding = None else: tile.stack.append(self.player.holding[0]) if len(self.player.holding) == 1: self.player.holding = None else: self.player.holding = self.player.holding[1:] # player could possibly set a box down and then be standing in an invalid position # nudge the player closer to the center of his tile to prevent this invalid state if fix_loc: if self.player.direction == 'left' or self.player.direction == 'right': left = self.player.direction == 'left' attempts = 10 while self.player.is_overlapping(left) and attempts > 0: cx = int(self.player.x) + 0.5 #cy = int(self.player.y) + 0.5 if (not horizontal) else self.player.y self.player.x = cx * .3 + self.player.x * .7 #self.player.y = cy * .3 + self.player.y * .7 attempts -= 1 if attempts == 0: # my paranoia of some bug causing an infinite loop here self.player.x = int(self.player.x) + 0.5 self.player.y = int(self.player.y) + 0.5 def process_input(self, events, pressed_keys): for event in events: if event.down: if event.action == 'full' or event.action == 'single': self.lift(event.action == 'full') elif event.action == 'menu': self.next = PriceMenu(self) elif event.action == 'order': self.next = OrderStuffMenu(self) elif event.action == 'pause': self.next = PauseMenu(self) v = 1.3 dx = 0 dy = 0 if pressed_keys.get('left'): dx = -1 elif pressed_keys.get('right'): dx = 1 if pressed_keys.get('up'): dy = -1 elif pressed_keys.get('down'): dy = 1 self.player.try_move(dx, dy) def lose_scene(self, type): self.next = DefeatScene(type, int(self.lifetime / 30.0), self.session.budget, self.session.things_sold) def update(self, counter): self.lifetime += 1 ensure_playing('shopmusic') self.session.update() # TODO: pause movement, make a noise while brining attention to the balance meter, and then move to the defeat screen a second later # probably done with a simple transition scene balance = self.session.is_defeat() if balance != 0: if balance == -1: type = 'hero_win' else: type = 'villain_win' self.lose_scene(type) return if len(self.session.get_disgruntled_count(True)) > 6: self.lose_scene('hero_angry') return elif len(self.session.get_disgruntled_count(False)) > 6: self.lose_scene('villain_angry') return if counter % 10 == 0: r = self.session.pop_restocking() if r != None: self.place_box(r) c = self.session.get_last_available_color() if c != self.last_color: self.last_color = c self.next = NewProductsMenu(self, c) customers = self.session.check_for_customers() if customers != None: for customer in customers: is_hero = customer.is_hero taken = {} for i in range(5): taken[i] = False for sprite in self.sprites: if sprite != self.player and sprite.is_hero == is_hero: taken[sprite.counter_slot] = True open = [] for k in taken.keys(): if not taken[k]: open.append(k) random.shuffle(open) if (len(open) > 0): customer.set_counter_slot(open[0]) self.sprites.append(customer) else: # counter full. reject customer self.session.reject_last_customer() for sprite in self.sprites: if sprite != self.player: sprite.automate(self.grid, self.session) new_sprites = [] for sprite in self.sprites: if not sprite.destroy_me: sprite.update(self.grid, self.sprites) new_sprites.append(sprite) self.sprites = new_sprites def render2(self, screen, counter): _LEFT2 = _LEFT * 2 _TOP2 = _TOP * 2 spacing = 28 for sprite in self.sprites: if sprite != self.player: if sprite.phase == 4: slot = sprite.counter_slot demand_x = int(16 * sprite.x - 8) * 2 - 2 + _LEFT2 demand_y = int(16 * sprite.y) * 2 + _TOP2 img = get_image('misc/demand_bubble') screen.blit(img, (demand_x, demand_y)) demands = sprite.demands height = len(demands) * spacing icon_y = demand_y + img.get_height() // 2 - height // 2 - 30 + 2 + spacing * 3 // 2 icon_x = demand_x + 8 + 2 for d in demands: screen.blit(get_image('boxes/' + d), (icon_x, icon_y)) icon_y += spacing gbarx = demand_x + 4 gbary = demand_y + img.get_height() + 8 gbarw = img.get_width() - 8 percent= 1.0 * sprite.gruntles / STARTING_GRUNTLES_COUNT gbarw0 = max(1, int(gbarw * percent)) gbarh = 3 if percent < 0.3: color = (255, 0, 0) elif percent > 0.7: color = (0, 220, 0) else: color = (255, 255, 0) pygame.draw.rect(screen, (0, 0, 0), pygame.Rect(gbarx - 1, gbary - 1, gbarw + 2, gbarh + 2)) pygame.draw.rect(screen, color, pygame.Rect(gbarx, gbary, gbarw0, gbarh)) self.draw_budget_bar(screen) self.draw_power_balance(screen) self.draw_options(screen) screen.blit(get_image('misc/radio'), (529, 615)) for is_hero in (False, True): x = 717 if is_hero else 86 y = 640 i = 0 x += 6 sprite_types = self.session.get_disgruntled_count(is_hero) while i < 6: sprite_type = None if (i >= len(sprite_types)) else sprite_types[i] if sprite_type != None: img = get_image('fwownyface/' + sprite_type) screen.blit(img, (x, y)) pygame.draw.rect(screen, (0, 0, 0), pygame.Rect(x - 3, y - 3, 22, 22), 1) i += 1 x += 28 def draw_options(self, screen): prices = get_small_text("Adjust prices (R)") order_more = get_small_text("Restock (T)") cloud = get_image('misc/thought_cloud') x = screen.get_width() - cloud.get_width() - 20 y = 0 screen.blit(cloud, (x, y)) screen.blit(prices, (x + 73, y + 40)) screen.blit(order_more, (x + 73, y + 70)) def draw_power_balance(self, screen): left = 416 top = 564 text = get_small_text("Power Balance") screen.blit(text, (left, top)) width = 220 y = top + text.get_height() + 10 x = left + text.get_width() // 2 - width // 2 evil = int(self.session.balance * width) good = width - evil height = 20 border = 3 pygame.draw.rect(screen, (123, 123, 123), pygame.Rect(x - border, y - border, width + border * 2, height + border * 2)) pygame.draw.rect(screen, (0, 0, 0), pygame.Rect(x, y, evil, height)) x += evil pygame.draw.rect(screen, (255, 255, 255), pygame.Rect(x, y, good, height)) def draw_budget_bar(self, screen): screen.blit(get_image('misc/budget_bar'), (10, 10)) screen.blit(get_text("Budget: " + format_money(self.session.budget)), (30, 38)) def render1(self, screen, rcounter): screen.fill((100, 180, 255)) self.render_room(screen, (_LEFT, _TOP), rcounter) def render_room(self, screen, roomtopleft, rcounter): rows = len(self.grid[0]) cols = len(self.grid) grid = self.grid left = roomtopleft[0] top = roomtopleft[1] if self.sprites_by_row == None: i = 0 self.sprites_by_row = [] while i < rows: self.sprites_by_row.append([]) i += 1 i = 0 while i < rows: self.sprites_by_row[i] = [] i += 1 for sprite in self.sprites: row = int(sprite.y) if row >= 0 and row < rows: self.sprites_by_row[row].append(sprite) row = 0 while row < rows: col = 0 while col < cols: tile = self.grid[col][row] img = tile.image if img != None: screen.blit(img, (col * 16 + left, row * 16 + top)) if tile.stack != None: i = 0 x = col + 0.5 y = row + 0.5 for box in tile.stack: box.render(screen, left, top, x, y, i) i += 1 col += 1 for sprite in self.sprites_by_row[row]: sprite.render(screen, left, top, rcounter) if sprite.holding != None: i = 4.7 for box in sprite.holding: box.render(screen, left, top, sprite.x, sprite.y, i) i += 1 row += 1
class PlayScene: def __init__(self): self.next = self self.session = Session() self.player = Sprite('player') self.player = Sprite('player') self.sprites = [self.player] self.last_color = None self.sprites_by_row = None self.lifetime = 0 # Forgive me father for I am about to sin. m = [ 'xx xx xx xx xx xx xx xx c7 c8 c8 c8 c8 c8 c8 c8 c8 c8 c9 xx xx xx xx xx xx xx xx', 'c7 c8 c8 c8 c8 c8 c9 xx c4 c5 c5 c5 c5 c5 c5 c5 c5 c5 c6 xx c7 c8 c8 c8 c8 c8 c9', 'c4 c5 c5 c5 c5 c5 c6 xx c4 f7 f8 f8 f8 f8 f8 f8 f8 f9 c6 xx c4 c5 c5 c5 c5 c5 c6', 'c4 f7 f8 f8 f8 f9 C1 c8 C3 f4 f5 f5 f5 f5 f5 f5 f5 f6 C1 c8 C3 f7 f8 f8 f8 f9 c6', 'c4 f4 f5 f5 f5 f6 c5 c5 c5 f4 f5 f5 f5 f5 f5 f5 f5 f6 c5 c5 c5 f4 f5 f5 f5 f6 c6', 'c4 f4 f5 f5 f5 F1 f8 f8 f8 F3 f5 f5 f5 f5 f5 f5 f5 F1 f8 f8 f8 F3 f5 f5 f5 f6 c6', 'c4 f4 f5 f5 f5 F7 f2 f2 f2 F9 f5 f5 f5 f5 f5 f5 f5 F7 f2 f2 f2 F9 f5 f5 f5 f6 c6', 'c4 f4 f5 f5 f5 f6 C7 c2 C9 f4 f5 f5 f5 f5 f5 f5 f5 f6 C7 c2 C9 f4 f5 f5 f5 f6 c6', 'c4 tl ct ct ct tr c6 xx c4 f4 f5 f5 f5 f5 f5 f5 f5 f6 c6 xx c4 tl ct ct ct tr c6', 'c4 bl cb cb cb br c6 xx c4 f4 f5 f5 f5 f5 f5 f5 f5 f6 c6 xx c4 bl cb cb cb br c6', 'c4 f4 f5 f5 f5 f6 c6 xx c4 f4 f5 f5 f5 f5 f5 f5 f5 f6 c6 xx c4 f4 f5 f5 f5 f6 c6', 'c4 f4 f5 f5 f5 f6 c6 xx c4 f4 f5 f5 f5 f5 f5 f5 f5 f6 c6 xx c4 f4 f5 f5 f5 f6 c6', 'c4 f4 f5 f5 f5 f6 c6 xx c4 f4 f5 f5 f5 f5 f5 f5 f5 f6 c6 xx c4 f4 f5 f5 f5 f6 c6', 'c4 f1 f2 f5 f2 f3 c6 xx c4 f1 f2 f2 f2 f2 f2 f2 f2 f3 c6 xx c4 f1 f2 f5 f2 f3 c6', 'c1 c2 c2 dd c2 c2 c3 xx c1 c2 c2 c2 c2 c2 c2 c2 c2 c2 c3 xx c1 c2 c2 dd c2 c2 c3' ] # Transpose this cols = [] row_count = len(m) col_count = len(m[0].split()) for i in range(len(m)): m[i] = m[i].split() x = 0 while x < col_count: col = [] y = 0 while y < row_count: col.append(Tile(m[y][x])) y += 1 x += 1 cols.append(col) self.grid = cols for i in range(5): v = self.grid[1 + i][8] h = self.grid[21 + i][8] v.is_counter = True h.is_counter = True v.counter_slot = i h.counter_slot = i v.counter_is_hero = False h.counter_is_hero = True self.player.x = 14.5 self.player.y = 12.5 #self.set_up_boxes(10) self.session.order_more('red', True) def place_box(self, key): storage_left = 11 storage_width = 5 storage_top = 2 storage_height = 5 box = Box(key) while True: x = storage_left + int(random.random() * storage_width) y = storage_top + int(random.random() * storage_height) dx = abs(x - self.player.x) dy = abs(y - self.player.y) if dx > 2 or dy > 2: break tile = self.grid[x][y] if tile.stack == None: tile.stack = [] tile.stack.append(box) def create_random_boxes(self, count): storage_left = 11 storage_width = 5 storage_top = 2 storage_height = 5 output = [] for i in range(count): box = self.session.get_random_box(True) x = int(random.random() * storage_width) + storage_left y = int(random.random() * storage_height) + storage_top output.append([box, x, y]) return output def set_up_boxes(self, count): boxes = self.create_random_boxes(count) for box in boxes: b = box[0] x = box[1] y = box[2] tile = self.grid[x][y] if tile.stack == None: tile.stack = [] tile.stack.append(b) def incorrect_order(self): play_sound("incorrect_order") pass def lift(self, is_full): dxdy = _direction_to_vector[self.player.direction] x = int(self.player.x) + dxdy[0] y = int(self.player.y) + dxdy[1] tile = self.grid[x][y] if self.player.holding == None: if tile.stack != None and not tile.is_counter: if is_full: self.player.holding = tile.stack tile.stack = None else: self.player.holding = [tile.stack[-1]] if len(tile.stack) == 1: tile.stack = None else: tile.stack = tile.stack[:-1] play_sound('lift') else: fix_loc = False if not tile.passable and not tile.is_counter: play_sound('cant_drop_box') return to_drop = [] if is_full: to_drop = self.player.holding[:] else: to_drop = self.player.holding[:1] item_sold = False if tile.is_counter: for sprite in self.sprites: if sprite.phase == 4: if sprite.counter_slot == tile.counter_slot: if sprite.is_hero == tile.counter_is_hero: sprite_demands = sprite.demands[:] for item_to_drop in to_drop: found = False i = 0 while i < len(sprite_demands): d = sprite_demands[i] if d == item_to_drop.key: found = True sprite_demands = sprite_demands[:i] + sprite_demands[ i + 1:] break i += 1 if not found: self.incorrect_order() return self.session.item_sold(sprite, item_to_drop.key) item_sold = True break if item_sold: play_sound('money_sound') elif tile.is_counter: # can't drop a box on a counter without selling it return else: play_sound('drop') if tile.stack == None: fix_loc = True tile.stack = [] if is_full: for item in self.player.holding: tile.stack.append(item) self.player.holding = None else: tile.stack.append(self.player.holding[0]) if len(self.player.holding) == 1: self.player.holding = None else: self.player.holding = self.player.holding[1:] # player could possibly set a box down and then be standing in an invalid position # nudge the player closer to the center of his tile to prevent this invalid state if fix_loc: if self.player.direction == 'left' or self.player.direction == 'right': left = self.player.direction == 'left' attempts = 10 while self.player.is_overlapping(left) and attempts > 0: cx = int(self.player.x) + 0.5 #cy = int(self.player.y) + 0.5 if (not horizontal) else self.player.y self.player.x = cx * .3 + self.player.x * .7 #self.player.y = cy * .3 + self.player.y * .7 attempts -= 1 if attempts == 0: # my paranoia of some bug causing an infinite loop here self.player.x = int(self.player.x) + 0.5 self.player.y = int(self.player.y) + 0.5 def process_input(self, events, pressed_keys): for event in events: if event.down: if event.action == 'full' or event.action == 'single': self.lift(event.action == 'full') elif event.action == 'menu': self.next = PriceMenu(self) elif event.action == 'order': self.next = OrderStuffMenu(self) elif event.action == 'pause': self.next = PauseMenu(self) v = 1.3 dx = 0 dy = 0 if pressed_keys.get('left'): dx = -1 elif pressed_keys.get('right'): dx = 1 if pressed_keys.get('up'): dy = -1 elif pressed_keys.get('down'): dy = 1 self.player.try_move(dx, dy) def lose_scene(self, type): self.next = DefeatScene(type, int(self.lifetime / 30.0), self.session.budget, self.session.things_sold) def update(self, counter): self.lifetime += 1 ensure_playing('shopmusic') self.session.update() # TODO: pause movement, make a noise while brining attention to the balance meter, and then move to the defeat screen a second later # probably done with a simple transition scene balance = self.session.is_defeat() if balance != 0: if balance == -1: type = 'hero_win' else: type = 'villain_win' self.lose_scene(type) return if len(self.session.get_disgruntled_count(True)) > 6: self.lose_scene('hero_angry') return elif len(self.session.get_disgruntled_count(False)) > 6: self.lose_scene('villain_angry') return if counter % 10 == 0: r = self.session.pop_restocking() if r != None: self.place_box(r) c = self.session.get_last_available_color() if c != self.last_color: self.last_color = c self.next = NewProductsMenu(self, c) customers = self.session.check_for_customers() if customers != None: for customer in customers: is_hero = customer.is_hero taken = {} for i in range(5): taken[i] = False for sprite in self.sprites: if sprite != self.player and sprite.is_hero == is_hero: taken[sprite.counter_slot] = True open = [] for k in taken.keys(): if not taken[k]: open.append(k) random.shuffle(open) if (len(open) > 0): customer.set_counter_slot(open[0]) self.sprites.append(customer) else: # counter full. reject customer self.session.reject_last_customer() for sprite in self.sprites: if sprite != self.player: sprite.automate(self.grid, self.session) new_sprites = [] for sprite in self.sprites: if not sprite.destroy_me: sprite.update(self.grid, self.sprites) new_sprites.append(sprite) self.sprites = new_sprites def render2(self, screen, counter): _LEFT2 = _LEFT * 2 _TOP2 = _TOP * 2 spacing = 28 for sprite in self.sprites: if sprite != self.player: if sprite.phase == 4: slot = sprite.counter_slot demand_x = int(16 * sprite.x - 8) * 2 - 2 + _LEFT2 demand_y = int(16 * sprite.y) * 2 + _TOP2 img = get_image('misc/demand_bubble') screen.blit(img, (demand_x, demand_y)) demands = sprite.demands height = len(demands) * spacing icon_y = demand_y + img.get_height( ) // 2 - height // 2 - 30 + 2 + spacing * 3 // 2 icon_x = demand_x + 8 + 2 for d in demands: screen.blit(get_image('boxes/' + d), (icon_x, icon_y)) icon_y += spacing gbarx = demand_x + 4 gbary = demand_y + img.get_height() + 8 gbarw = img.get_width() - 8 percent = 1.0 * sprite.gruntles / STARTING_GRUNTLES_COUNT gbarw0 = max(1, int(gbarw * percent)) gbarh = 3 if percent < 0.3: color = (255, 0, 0) elif percent > 0.7: color = (0, 220, 0) else: color = (255, 255, 0) pygame.draw.rect( screen, (0, 0, 0), pygame.Rect(gbarx - 1, gbary - 1, gbarw + 2, gbarh + 2)) pygame.draw.rect(screen, color, pygame.Rect(gbarx, gbary, gbarw0, gbarh)) self.draw_budget_bar(screen) self.draw_power_balance(screen) self.draw_options(screen) screen.blit(get_image('misc/radio'), (529, 615)) for is_hero in (False, True): x = 717 if is_hero else 86 y = 640 i = 0 x += 6 sprite_types = self.session.get_disgruntled_count(is_hero) while i < 6: sprite_type = None if ( i >= len(sprite_types)) else sprite_types[i] if sprite_type != None: img = get_image('fwownyface/' + sprite_type) screen.blit(img, (x, y)) pygame.draw.rect(screen, (0, 0, 0), pygame.Rect(x - 3, y - 3, 22, 22), 1) i += 1 x += 28 def draw_options(self, screen): prices = get_small_text("Adjust prices (R)") order_more = get_small_text("Restock (T)") cloud = get_image('misc/thought_cloud') x = screen.get_width() - cloud.get_width() - 20 y = 0 screen.blit(cloud, (x, y)) screen.blit(prices, (x + 73, y + 40)) screen.blit(order_more, (x + 73, y + 70)) def draw_power_balance(self, screen): left = 416 top = 564 text = get_small_text("Power Balance") screen.blit(text, (left, top)) width = 220 y = top + text.get_height() + 10 x = left + text.get_width() // 2 - width // 2 evil = int(self.session.balance * width) good = width - evil height = 20 border = 3 pygame.draw.rect( screen, (123, 123, 123), pygame.Rect(x - border, y - border, width + border * 2, height + border * 2)) pygame.draw.rect(screen, (0, 0, 0), pygame.Rect(x, y, evil, height)) x += evil pygame.draw.rect(screen, (255, 255, 255), pygame.Rect(x, y, good, height)) def draw_budget_bar(self, screen): screen.blit(get_image('misc/budget_bar'), (10, 10)) screen.blit(get_text("Budget: " + format_money(self.session.budget)), (30, 38)) def render1(self, screen, rcounter): screen.fill((100, 180, 255)) self.render_room(screen, (_LEFT, _TOP), rcounter) def render_room(self, screen, roomtopleft, rcounter): rows = len(self.grid[0]) cols = len(self.grid) grid = self.grid left = roomtopleft[0] top = roomtopleft[1] if self.sprites_by_row == None: i = 0 self.sprites_by_row = [] while i < rows: self.sprites_by_row.append([]) i += 1 i = 0 while i < rows: self.sprites_by_row[i] = [] i += 1 for sprite in self.sprites: row = int(sprite.y) if row >= 0 and row < rows: self.sprites_by_row[row].append(sprite) row = 0 while row < rows: col = 0 while col < cols: tile = self.grid[col][row] img = tile.image if img != None: screen.blit(img, (col * 16 + left, row * 16 + top)) if tile.stack != None: i = 0 x = col + 0.5 y = row + 0.5 for box in tile.stack: box.render(screen, left, top, x, y, i) i += 1 col += 1 for sprite in self.sprites_by_row[row]: sprite.render(screen, left, top, rcounter) if sprite.holding != None: i = 4.7 for box in sprite.holding: box.render(screen, left, top, sprite.x, sprite.y, i) i += 1 row += 1