User prompt
I still can't
User prompt
Please fix the bug: 'Timeout.tick error: Cannot set properties of null (setting 'gridX')' in or related to this line: 'selectedCandy.gridX = oldGrid1.x;' Line Number: 441
Code edit (1 edits merged)
Please save this source code
User prompt
Sweet Cascades
Initial prompt
import pygame import random import sys from pygame.locals import * # Initialize pygame pygame.init() # Constants SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 GRID_SIZE = 8 CELL_SIZE = 64 GRID_OFFSET_X = (SCREEN_WIDTH - GRID_SIZE * CELL_SIZE) // 2 GRID_OFFSET_Y = 150 FPS = 60 # Colors WHITE = (255, 255, 255) BLACK = (0, 0, 0) BACKGROUND_COLOR = (253, 245, 230) # Creamy background # Candy colors CANDY_COLORS = [ (255, 50, 50), # Red (50, 255, 50), # Green (50, 50, 255), # Blue (255, 255, 50), # Yellow (255, 50, 255), # Purple (50, 255, 255), # Cyan ] class Candy: def __init__(self, row, col, color_idx): self.row = row self.col = col self.color_idx = color_idx self.x = 0 self.y = 0 self.target_y = 0 self.target_x = 0 self.is_moving = False self.is_selected = False self.special_type = None # 'bomb', 'rainbow', 'lollipop' def update_position(self): if self.x < self.target_x: self.x += 5 self.is_moving = True elif self.x > self.target_x: self.x -= 5 self.is_moving = True else: self.x = self.target_x if self.y < self.target_y: self.y += 5 self.is_moving = True elif self.y > self.target_y: self.y -= 5 self.is_moving = True else: self.y = self.target_y self.is_moving = False def draw(self, surface): color = CANDY_COLORS[self.color_idx] rect = pygame.Rect( GRID_OFFSET_X + self.col * CELL_SIZE + self.x + 5, GRID_OFFSET_Y + self.row * CELL_SIZE + self.y + 5, CELL_SIZE - 10, CELL_SIZE - 10 ) # Draw candy base pygame.draw.rect(surface, color, rect, border_radius=10) # Add candy highlights highlight = pygame.Surface((CELL_SIZE-10, CELL_SIZE-10), pygame.SRCALPHA) pygame.draw.rect(highlight, (*color[:3], 50), highlight.get_rect(), border_radius=10) surface.blit(highlight, rect) # Draw selection border if self.is_selected: pygame.draw.rect(surface, WHITE, rect, 3, border_radius=10) # Draw special candy indicators if self.special_type == 'bomb': pygame.draw.circle(surface, BLACK, rect.center, 10) elif self.special_type == 'rainbow': for i in range(6): pygame.draw.arc(surface, CANDY_COLORS[i], rect, i * 0.8, (i+1) * 0.8, 5) elif self.special_type == 'lollipop': pygame.draw.circle(surface, WHITE, rect.center, 15, 3) class Game: def __init__(self): self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) pygame.display.set_caption("Sweet Cascades") self.clock = pygame.time.Clock() self.font = pygame.font.SysFont('Arial', 24) self.big_font = pygame.font.SysFont('Arial', 36) self.grid = [] self.selected_candy = None self.score = 0 self.moves_left = 30 self.level = 1 self.target_score = 1000 self.initialize_grid() def initialize_grid(self): self.grid = [] for row in range(GRID_SIZE): grid_row = [] for col in range(GRID_SIZE): # Make sure we don't create matches at the start while True: color_idx = random.randint(0, len(CANDY_COLORS) - 1) # Check horizontal matches if col >= 2: if (grid_row[col-1].color_idx == color_idx and grid_row[col-2].color_idx == color_idx): continue # Check vertical matches if row >= 2: if (self.grid[row-1][col].color_idx == color_idx and self.grid[row-2][col].color_idx == color_idx): continue break candy = Candy(row, col, color_idx) candy.target_x = 0 candy.target_y = 0 grid_row.append(candy) self.grid.append(grid_row) def draw(self): # Draw background self.screen.fill(BACKGROUND_COLOR) # Draw title title = self.big_font.render("Sweet Cascades", True, (200, 50, 100)) self.screen.blit(title, (SCREEN_WIDTH // 2 - title.get_width() // 2, 20)) # Draw score and moves score_text = self.font.render(f"Score: {self.score}", True, BLACK) moves_text = self.font.render(f"Moves: {self.moves_left}", True, BLACK) level_text = self.font.render(f"Level: {self.level}", True, BLACK) target_text = self.font.render(f"Target: {self.target_score}", True, BLACK) self.screen.blit(score_text, (50, 80)) self.screen.blit(moves_text, (200, 80)) self.screen.blit(level_text, (350, 80)) self.screen.blit(target_text, (500, 80)) # Draw grid background grid_bg = pygame.Rect( GRID_OFFSET_X - 5, GRID_OFFSET_Y - 5, GRID_SIZE * CELL_SIZE + 10, GRID_SIZE * CELL_SIZE + 10 ) pygame.draw.rect(self.screen, (220, 220, 220), grid_bg, border_radius=15) # Draw candies for row in self.grid: for candy in row: candy.draw(self.screen) # Draw game over or level complete message if self.moves_left <= 0: if self.score >= self.target_score: message = self.big_font.render("Level Complete!", True, (0, 200, 0)) else: message = self.big_font.render("Game Over!", True, (200, 0, 0)) self.screen.blit(message, (SCREEN_WIDTH // 2 - message.get_width() // 2, SCREEN_HEIGHT - 100)) pygame.display.flip() def handle_click(self, pos): if self.moves_left <= 0: return x, y = pos # Check if click is within grid if (GRID_OFFSET_X <= x < GRID_OFFSET_X + GRID_SIZE * CELL_SIZE and GRID_OFFSET_Y <= y < GRID_OFFSET_Y + GRID_SIZE * CELL_SIZE): col = (x - GRID_OFFSET_X) // CELL_SIZE row = (y - GRID_OFFSET_Y) // CELL_SIZE if 0 <= row < GRID_SIZE and 0 <= col < GRID_SIZE: clicked_candy = self.grid[row][col] if self.selected_candy is None: # First selection self.selected_candy = clicked_candy clicked_candy.is_selected = True else: # Second selection - check if adjacent if (abs(self.selected_candy.row - clicked_candy.row) == 1 and self.selected_candy.col == clicked_candy.col) or ( abs(self.selected_candy.col - clicked_candy.col) == 1 and self.selected_candy.row == clicked_candy.row): # Swap candies self.swap_candies(self.selected_candy, clicked_candy) self.moves_left -= 1 # Check for matches after swap matches = self.find_matches() if not matches: # No matches, swap back self.swap_candies(self.selected_candy, clicked_candy) self.moves_left += 1 else: # Process matches self.process_matches(matches) # Deselect self.selected_candy.is_selected = False self.selected_candy = None clicked_candy.is_selected = False def swap_candies(self, candy1, candy2): # Swap positions in grid self.grid[candy1.row][candy1.col], self.grid[candy2.row][candy2.col] = ( self.grid[candy2.row][candy2.col], self.grid[candy1.row][candy1.col] ) # Swap row and col attributes candy1.row, candy2.row = candy2.row, candy1.row candy1.col, candy2.col = candy2.col, candy1.col # Set target positions for animation candy1.target_x = 0 candy1.target_y = 0 candy2.target_x = 0 candy2.target_y = 0 def find_matches(self): matches = [] # Check horizontal matches for row in range(GRID_SIZE): for col in range(GRID_SIZE - 2): if (self.grid[row][col].color_idx == self.grid[row][col+1].color_idx == self.grid[row][col+2].color_idx): match = [] # Find all consecutive matching candies for c in range(col, GRID_SIZE): if self.grid[row][c].color_idx == self.grid[row][col].color_idx: match.append(self.grid[row][c]) else: break if len(match) >= 3: matches.append(match) # Check vertical matches for col in range(GRID_SIZE): for row in range(GRID_SIZE - 2): if (self.grid[row][col].color_idx == self.grid[row+1][col].color_idx == self.grid[row+2][col].color_idx): match = [] # Find all consecutive matching candies for r in range(row, GRID_SIZE): if self.grid[r][col].color_idx == self.grid[row][col].color_idx: match.append(self.grid[r][col]) else: break if len(match) >= 3: matches.append(match) return matches def process_matches(self, matches): # Create special candies for larger matches for match in matches: if len(match) == 4: # Create a bomb (random candy in the match) candy = random.choice(match) candy.special_type = 'bomb' elif len(match) >= 5: # Create a rainbow candy (first candy in the match) match[0].special_type = 'rainbow' # Lollipop could be created for L or T shapes (not implemented here) # Remove matched candies and calculate score matched_positions = set() for match in matches: for candy in match: if (candy.row, candy.col) not in matched_positions: matched_positions.add((candy.row, candy.col)) self.score += 10 * len(match) # Special candy effects if candy.special_type == 'bomb': self.score += 50 # Clear row and column for r in range(GRID_SIZE): matched_positions.add((r, candy.col)) for c in range(GRID_SIZE): matched_positions.add((candy.row, c)) elif candy.special_type == 'rainbow': self.score += 100 # Clear all candies of same color color = candy.color_idx for row in self.grid: for c in row: if c.color_idx == color: matched_positions.add((c.row, c.col)) # Remove matched candies for row, col in matched_positions: self.grid[row][col] = None # Drop candies down self.drop_candies() # Fill empty spaces self.fill_empty_spaces() # Check for new matches after filling new_matches = self.find_matches() if new_matches: self.process_matches(new_matches) def drop_candies(self): for col in range(GRID_SIZE): # Count empty spaces in column empty_rows = [] for row in range(GRID_SIZE-1, -1, -1): if self.grid[row][col] is None: empty_rows.append(row) elif empty_rows: # Move candy down to the lowest empty space lowest_empty = empty_rows.pop(0) self.grid[lowest_empty][col] = self.grid[row][col] self.grid[row][col] = None self.grid[lowest_empty][col].row = lowest_empty self.grid[lowest_empty][col].target_y = 0 empty_rows.append(row) def fill_empty_spaces(self): for row in range(GRID_SIZE): for col in range(GRID_SIZE): if self.grid[row][col] is None: color_idx = random.randint(0, len(CANDY_COLORS) - 1) candy = Candy(row, col, color_idx) candy.target_y = -CELL_SIZE # Start above the grid for falling animation candy.y = -CELL_SIZE self.grid[row][col] = candy def update(self): # Update candy positions for animations for row in self.grid: for candy in row: if candy: candy.update_position() # Check level completion if self.score >= self.target_score and self.moves_left > 0: self.level += 1 self.target_score += self.level * 500 self.moves_left = 30 self.initialize_grid() def run(self): running = True while running: for event in pygame.event.get(): if event.type == QUIT: running = False elif event.type == MOUSEBUTTONDOWN: self.handle_click(event.pos) self.update() self.draw() self.clock.tick(FPS) pygame.quit() sys.exit() if __name__ == "__main__": game = Game() game.run()
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
}); /****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});