m654
m654

Reputation: 158

Highlighting tile on Pygame tilemap

I'm making a simple tile-based game with Pygame.

Currently, it displays a 10x10 grid of randomly selected tiles. That part is working perfectly, but I have a problem with highlighting.

When you mouse over a tile, it should load a greyish tile at about half opacity. It loads, but the opacity isn't working correctly. If you put the mouse on a tile, it loads correctly with the opacity and all. But if you move the mouse around the tile, it turns normal, without opacity.

I think it's happening because it's loading the highlighting tile every time an event occurs, but I'm not sure how to fix it.

I'm using a class called Tilemap that I made to generate and draw the tilemap. I think it's something in the draw() function that's causing all of this.

import pygame
import sys
import random
from pygame.locals import *

running = True

class Tilemap:
    tilemap = []
    ht = None # ht = highlight texture

    def __init__(self, height, width, tilesize, textures):
        self.height = height # How many tiles high it is
        self.width = width # How many tiles wide it is
        self.tilesize = tilesize # How many pixels each tile is
        self.textures = textures # The textures
        self.size = (self.width*self.tilesize,self.height*self.tilesize)

    def generate_random(self):
        # Generate a random tilemap
        self.tilemap = [[random.randint(0, len(
            self.textures)-1) for e in range(self.width)] for e in range(
                self.height)]

    def draw(self, display, mouse=None):
        mouse = mouse
        # Draw the map
        for row in range(self.width):
            for column in range(self.height):



                texture = self.textures[self.tilemap[row][column]]
                # Highlight a tile (this is where the problem is)
                if self.ht != None:
                    if mouse[0] >= (column*self.tilesize) and mouse[0] <= (
                        column*self.tilesize)+self.tilesize:
                        if mouse[1] >= (row*self.tilesize) and mouse[1] <= (
                            row*self.tilesize)+self.tilesize:
                            texture = self.ht

                display.blit(texture,
                             (column*self.tilesize, row*self.tilesize))




tilemap = Tilemap(10,10,40,
                  # Load the textures
                  {0: pygame.image.load("tile1.png"),
                   1: pygame.image.load("tile2.png")
                   }
                  )

tilemap.generate_random() # Generate a random tilemap

pygame.init()
DISPLAYSURF = pygame.display.set_mode((tilemap.size))
# Load the highlighter
tilemap.ht = pygame.image.load("highlight.png").convert_alpha()

while running:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

        # Draw the tilemap
        tilemap.draw(DISPLAYSURF, pygame.mouse.get_pos())

    pygame.display.update()

If you need more explanation feel free to ask!

Upvotes: 0

Views: 1276

Answers (2)

lukevp
lukevp

Reputation: 715

Each time you draw to a surface in Pygame, the previous frame's data persists. Since you are drawing alpha, the previous, partially-transparent drawing is still in the same location, and you are drawing a partially-transparent tile over the same spot with each frame. That causes that square to get closer and closer to the final color. What you would typically do is erase the area you are blitting to and then re-draw. In this case you'd want to do this before your display.blit:

display.fill((0,0,0), (0, 0, column*self.tilesize, row*self.tilesize))
display.blit(texture, (column*self.tilesize, row*self.tilesize))

This will work so long as your background is black. If you end up having an image for a background, you would just blit the background image slice there instead.

This code is untested since I don't have your sample PNGs, but if you have an issue please let me know and I will update the answer.

Upvotes: 0

njoosse
njoosse

Reputation: 549

If you add the line tilemap.ht.set_alpha(<VALUE>) just before the while running:

# Load the highlighter
tilemap.ht = pygame.image.load("highlight.png").convert(8)
tilemap.ht.set_alpha(64)

the tile will be transparent. The value is between 0 and 255 (inclusive). I also changed the convert_alpha() to a convert(8) so it is 8-bit.

Source:

how to use pygame set_alpha() on a picture

Additional note: You may want to implement a tracking of which square is highlighted so that it does not draw again until the new tile is selected. At this point it will continue to draw squares over the selected tile when the mouse is moved, causing it to become less transparent.

Example:

enter image description here

initial selection vs. continued selection

Upvotes: 1

Related Questions