2

I have an assignment where we need to create functions to display text onto the screen in python/pygame. This part I understand. What I don't is that you're supposed to create a function which creates a drop shadow. I know how to make the shadow I just don't know how to make another function to do it and have the option to call from a pre existing text one. This is what I have so far

import pygame
import sys
pygame.init()

screenSizeX = 1080
screenSizeY = 720
screenSize = (screenSizeX,screenSizeY)
screen = pygame.display.set_mode(screenSize,0)
pygame.display.set_caption("Test Functions")

WHITE = (255,255,255)
GREEN = (0,255,0)
BLUE = (0,0,255)
RED = (255,0,0)
YELLOW = (255,255,0)
BLACK = (0,0,0)
MAGENTA = (139,0,139)

def horCenter(font, size, text, colour, y, shadow, pos):
    if shadow == True:

    fontTitle = pygame.font.SysFont(font, size)
    textTitle = fontTitle.render(text, True, colour)
    textWidth = textTitle.get_width()
    screen.blit(textTitle, (screenSizeX/2 - textWidth/2, y))

def verCenter(font, size, text, colour, x):
    fontTitle = pygame.font.SysFont(font, size)
    textTitle = fontTitle.render(text, True, colour)
    textHeight = textTitle.get_height()
    screen.blit(textTitle, (x, screenSizeY/2 - textHeight/2))

def cenCenter(font, size, text, colour):
    fontTitle = pygame.font.SysFont(font, size)
    textTitle = fontTitle.render(text, True, colour)
    textHeight = textTitle.get_height()
    textWidth = textTitle.get_width()
    screen.blit(textTitle, (screenSizeX/2 - textWidth/2, screenSizeY/2 - textHeight/2))   




pygame.display.update()

go = True
while go:
    for event in pygame.event.get():
        if event.type ==pygame.QUIT:
            go = False


    screen.fill(WHITE)
    horCenter("Comic Sans MS", 40, "Text1", MAGENTA, 100)
    verCenter("Georgia", 10, "Tex2", GREEN, 500)
    cenCenter("Impact", 50, "Text3", RED)
    verCenter("Verdana", 60, "89274", BLACK, 50)
    pygame.display.update()

pygame.quit()
sys.exit()
Kingsley
  • 14,398
  • 5
  • 31
  • 53
Fifer
  • 51
  • 1
  • 6
  • Say you want to draw text at `(x,y)`. Write the drop-shadow text first at `(x+5, y+5)` in dark-grey before over-writing the text afterwards at `(x,y)`. – Kingsley Oct 24 '18 at 01:59

3 Answers3

4

A dropshadow can be rendered by drawing the text twice. The first is a grey version of the text at an offset, then the actual text at the original position.

def dropShadowText(screen, text, size, x, y, colour=(255,255,255), drop_colour=(128,128,128), font=None):
    # how much 'shadow distance' is best?
    dropshadow_offset = 1 + (size // 15)
    text_font = pygame.font.Font(font, size)
    # make the drop-shadow
    text_bitmap = text_font.render(text, True, drop_colour)
    screen.blit(text_bitmap, (x+dropshadow_offset, y+dropshadow_offset) )
    # make the overlay text
    text_bitmap = text_font.render(text, True, colour)
    screen.blit(text_bitmap, (x, y) )

So you can call it like:

dropShadowText(screen, "Hello World", 36, 50, 50)
Kingsley
  • 14,398
  • 5
  • 31
  • 53
1

I figured it out with help from Kingsley's response. Now you can choose to add a shadow or not, where its positioned and what colour it is. Maybe there is an easier way but this worked for me.

import pygame
import sys
pygame.init()

screenSizeX = 1080
screenSizeY = 720
screenSize = (screenSizeX,screenSizeY)
screen = pygame.display.set_mode(screenSize,0)
pygame.display.set_caption("Test Functions")

WHITE = (255,255,255)
GREEN = (0,255,0)
BLUE = (0,0,255)
RED = (255,0,0)
YELLOW = (255,255,0)
BLACK = (0,0,0)
MAGENTA = (139,0,139)


def horCenter(font, size, text, colour, yPos, shadow, shadowPlace, shadowColour):   
    fontTitle = pygame.font.SysFont(font, size)
    textTitle = fontTitle.render(text, True, colour)
    textWidth = textTitle.get_width()
    xPos = screenSizeX/2 - textWidth/2
    if shadow == "True":
        dropShadow(font,size,text,colour, xPos,yPos, shadowPlace, shadowColour)
    else:
        screen.blit(textTitle, (xPos, yPos)) 

def verCenter(font, size, text, colour, xPos, shadow, shadowPlace, shadowColour):
    fontTitle = pygame.font.SysFont(font, size)
    textTitle = fontTitle.render(text, True, colour)
    textHeight = textTitle.get_height()
    yPos = screenSizeY/2 - textHeight/2
    if shadow == "True":
        dropShadow(font,size,text,colour, xPos,yPos, shadowPlace, shadowColour)
    else:
        screen.blit(textTitle, (xPos, yPos))

def cenCenter(font, size, text, colour, shadow, shadowPlace, shadowColour):
    fontTitle = pygame.font.SysFont(font, size)
    textTitle = fontTitle.render(text, True, colour)
    textHeight = textTitle.get_height()
    textWidth = textTitle.get_width()
    xPos = screenSizeX/2 - textWidth/2
    yPos = screenSizeY/2 - textHeight/2
    if shadow == "True":
        dropShadow(font,size,text,colour, xPos,yPos, shadowPlace, shadowColour)
    else:
        screen.blit(textTitle, (xPos, yPos))


def dropShadow(font, size, text, colour, xPos,yPos, shadowPlace, shadowColour):
    fontTitle = pygame.font.SysFont(font, size)
    textTitle = fontTitle.render(text, True, colour)
    shadowTitle = fontTitle.render(text, True, shadowColour)
    if shadowPlace == "bottomRight":
        newXPos = xPos +2
        newYPos = yPos + 2
        screen.blit(shadowTitle, (newXPos,newYPos))
        screen.blit(textTitle, (xPos,yPos))
    elif shadowPlace == "bottomLeft":
        newXPos = xPos - 2
        newYPos = yPos + 2
        screen.blit(shadowTitle, (newXPos, newYPos))
        screen.blit(textTitle, (xPos, yPos))
    elif shadowPlace == "topRight":
        newXPos = xPos - 2
        newYPos = yPos - 2
        screen.blit(shadowTitle, (newXPos, newYPos))
        screen.blit(textTitle, (xPos, yPos))
    elif shadowPlace == "topLeft":
        newXPos = xPos + 2
        newYPos = yPos - 2
        screen.blit(shadowTitle, (newXPos, newYPos))
        screen.blit(textTitle, (xPos, yPos))


pygame.display.update()

go = True
while go:
    for event in pygame.event.get():
        if event.type ==pygame.QUIT:
            go = False


    screen.fill(WHITE)
    horCenter("Comic Sans MS", 40, "Thanos", MAGENTA, 100, "True", "topLeft", YELLOW)
    verCenter("Georgia", 10, "HULK SMASH", GREEN, 800, "True", "bottomRight", BLACK)
    cenCenter("Impact", 50, "MARVEL", RED, "True", "bottomRight", BLACK)
    verCenter("Verdana", 60, "Black Widow", BLACK, 50, "True", "topRight", RED)
    pygame.display.update()

pygame.quit()
sys.exit()
Fifer
  • 51
  • 1
  • 6
0

If you want a transparent drop shadow, you have to:

def renderTextDropShadow(font, text, color, dx, dy, shadowColor, shadowAlpha):
    textSize = font.size(text)
    surf = pygame.Surface((textSize[0] + abs(dx), textSize[1] + abs(dy)), pygame.SRCALPHA)
    shadowSurf = font.render(text, True, shadowColor)
    shadowSurf.set_alpha(shadowAlpha)
    textSurf = font.render(text, True, color)
    surf.blit(shadowSurf, (max(0, dx), max(0, dy)))
    surf.blit(textSurf, (max(0, -dx), max(0, -dy)))
    return surf

Minimal example:

import pygame

def renderTextDropShadow(font, text, color, dx, dy, shadowColor=(127, 127, 127), shadowAlpha = 127):
    textSize = font.size(text)
    surf = pygame.Surface((textSize[0] + abs(dx), textSize[1] + abs(dy)), pygame.SRCALPHA)
    shadowSurf = font.render(text, True, shadowColor)
    shadowSurf.set_alpha(shadowAlpha)
    textSurf = font.render(text, True, color)
    surf.blit(shadowSurf, (max(0, dx), max(0, dy)))
    surf.blit(textSurf, (max(0, -dx), max(0, -dy)))
    return surf

pygame.init()
window = pygame.display.set_mode((700, 200))
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 150)

textSurf = renderTextDropShadow(font, 'Hello World!', (0, 0, 0), -15, 10)

background = pygame.Surface(window.get_size())
ts, w, h, c1, c2 = 50, *window.get_size(), (255, 255, 255), (255, 164, 196)
tiles = [((x*ts, y*ts, ts, ts), c1 if (x+y) % 2 == 0 else c2) for x in range((w+ts-1)//ts) for y in range((h+ts-1)//ts)]
for rect, color in tiles:
    pygame.draw.rect(background, color, rect)

run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    window.blit(background, (0, 0))
    window.blit(textSurf, textSurf.get_rect(center = window.get_rect().center))
    pygame.display.flip()

pygame.quit()
exit()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174