Python Forum
Thread Rating:
  • 1 Vote(s) - 4 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyGame] Common Tasks
#11
Color Surface
An example of 2 different methods to draw a new color over a surface within pygame
#no other libs requires other than pygame def colorize(image, newColor): """ Create a "colorized" copy of a surface (replaces RGB values with the given color, preserving the per-pixel alphas of original). :param image: Surface to create a colorized copy of :param newColor: RGB color to use (original alpha values are preserved) :return: New colorized Surface instance """ image = image.copy() # zero out RGB values image.fill((0, 0, 0, 255), None, pg.BLEND_RGBA_MULT) # add in new RGB values image.fill(newColor[0:3] + (0,), None, pg.BLEND_RGBA_ADD) return image #requires numpy module to be installed def color_surface(surface, red, green, blue): '''requires numpy module on users end''' arr = pg.surfarray.pixels3d(surface) arr[:,:,0] = red arr[:,:,1] = green arr[:,:,2] = blue
Recommended Tutorials:
Reply
#12
Resizable Window
Go to the corner of the window and make it smaller
import pygame as pg import random class Ball: def __init__(self, screen_rect): self.screen_rect = screen_rect self.image = pg.Surface([50,50]).convert() self.image.fill((255,0,0)) self.rect = self.image.get_rect() self.speed_init = 10 self.speed = self.speed_init self.set_ball() def set_ball(self): self.vel = [random.choice([-1,1]), 0] self.rect.center = self.screen_rect.center self.true_pos = list(self.rect.center) self.speed = self.speed_init def move(self): if self.rect.left <= 0: self.vel[0] *= -1 elif self.rect.right >= self.screen_rect.right: self.vel[0] *= -1 self.true_pos[0] += self.vel[0] * self.speed #self.true_pos[1] += self.vel[1] * self.speed self.rect.center = self.true_pos def update(self, screen_rect): self.screen_rect = screen_rect self.move() def draw(self, surf): surf.blit(self.image, self.rect) class Control: def __init__(self): self.resolutions = [(300,200), (600,400),(800, 600), (928, 696)] self.render_size = self.resolutions[-1] #largest self.screen = pg.display.set_mode(self.resolutions[-1], pg.RESIZABLE) self.screen_rect = self.screen.get_rect() self.render_surf = pg.Surface(self.render_size).convert() #pg.event.clear(pg.VIDEORESIZE) self.clock = pg.time.Clock() self.done = False self.fps = 60 self.ball = Ball(self.screen_rect) def event_loop(self): for event in pg.event.get(): if event.type == pg.QUIT: self.done = True elif event.type == pg.VIDEORESIZE: self.on_resize(event.size) #pg.event.clear(pg.VIDEORESIZE) def on_resize(self, size): if size == self.screen_rect.size: return res_index = self.resolutions.index(self.screen_rect.size) adjust = 1 if size > self.screen_rect.size else -1 if 0 <= res_index+adjust < len(self.resolutions): new_size = self.resolutions[res_index+adjust] else: new_size = self.screen_rect.size self.screen = pg.display.set_mode(new_size, pg.RESIZABLE) self.screen_rect.size = new_size self.set_scale() def set_scale(self): w_ratio = self.render_size[0]/float(self.screen_rect.w) h_ratio = self.render_size[1]/float(self.screen_rect.h) self.scale = (w_ratio, h_ratio) def update(self): self.ball.update(self.render_surf.get_rect()) #give obj updated screen size def render(self): if self.render_size != self.screen_rect.size: scale_args = (self.render_surf, self.screen_rect.size, self.screen) pg.transform.smoothscale(*scale_args) else: self.screen.blit(self.render_surf, (0, 0)) self.render_surf.fill((255,255,255)) self.ball.draw(self.render_surf) def game_loop(self): while not self.done: self.event_loop() self.update() self.render() pg.display.update() self.clock.tick(self.fps) pg.init() app = Control() app.game_loop() pg.quit()
Recommended Tutorials:
Reply
#13
Rotate Around a Point
LEFT or RIGHT / A or D keys to move around the point.
import pygame as pg import math class Rotator: def __init__(self, screen_rect): self.radar = screen_rect.center self.radar_len = 100 self.angle = 0 self.image = pg.Surface([25,25]).convert() self.get_pos() self.rect = self.image.get_rect(center=(self.x, self.y)) self.image.fill((255,0,0)) self.speed = 200 def render(self, screen): screen.blit(self.image, self.rect) pg.draw.line(screen, (255,255,255), self.radar, (self.x,self.y), 1) def update(self, seconds): keys = pg.key.get_pressed() self.get_pos() self.rect.center = (self.x, self.y) if keys[pg.K_RIGHT] or keys[pg.K_d]: self.angle -= self.speed * seconds elif keys[pg.K_LEFT] or keys[pg.K_a]: self.angle += self.speed * seconds def get_pos(self): self.x = self.radar[0] + math.cos(math.radians(self.angle)) * self.radar_len self.y = self.radar[1] + math.sin(math.radians(self.angle)) * self.radar_len if __name__ == '__main__': running = True pg.init() screen = pg.display.set_mode((600,400)) screen_rect = screen.get_rect() rotator = Rotator(screen_rect) clock = pg.time.Clock() seconds = 0 while running: screen.fill((0,0,0)) for event in pg.event.get(): if event.type == pg.QUIT: running = False elif event.type == pg.MOUSEBUTTONDOWN: rotator.radar = pg.mouse.get_pos() rotator.update(seconds) rotator.render(screen) pg.display.set_caption('x,y:{} {}'.format(rotator.x, rotator.y)) pg.display.update() milli = clock.tick(60) seconds = milli / 1000.0
Recommended Tutorials:
Reply
#14
Draw Shape to Surface
Here is an example of a pygame rect drawn to a custom surface. You can only see the half circle because its positioned at the bottom of that surface. As for the surface not showing, it has disappeared in the background because its color is set as the color key to hide. This can be useful to create odd shapes. An example would be trying to follow a clickable or mouse highlight pattern from a background for example.
import pygame pygame.init() screen = pygame.display.set_mode((800,600)) screen_rect = screen.get_rect() circle = pygame.Surface([500,300]).convert() circle.fill((255,0,255)) #make abnormal bg color circle.set_colorkey((255,0,255)) #hide bg pygame.draw.circle(circle, (200,200,0), screen_rect.center, 25, 0) circle_rect = circle.get_rect() running = True while running: screen.fill((255,255,255)) for event in pygame.event.get(): if event.type == pygame.QUIT: running = False keys = pygame.key.get_pressed() if keys[pygame.K_RIGHT]: circle_rect.x += 1 elif keys[pygame.K_LEFT]: circle_rect.x -= 1 screen.blit(circle, circle_rect) pygame.display.update()
Recommended Tutorials:
Reply
#15
Basic button class example

import pygame as pg pg.init() def flip_color(): global bg_white bg_white = not bg_white class Button: def __init__(self, rect, command): self.color = (255,0,0) self.rect = pg.Rect(rect) self.image = pg.Surface(self.rect.size) self.image.fill(self.color) self.command = command def render(self, screen): screen.blit(self.image, self.rect) def get_event(self, event): if event.type == pg.MOUSEBUTTONDOWN and event.button == 1: if self.rect.collidepoint(pg.mouse.get_pos()): self.command() screen = pg.display.set_mode((800,600)) screen_rect = screen.get_rect() running = True bg_white = False btn = Button((10,10,105,25), flip_color) while running: for event in pg.event.get(): if event.type == pg.QUIT: running = False btn.get_event(event) if bg_white: screen.fill((255,255,255)) else: screen.fill((0,0,0)) btn.render(screen) pg.display.update()
Recommended Tutorials:
Reply
#16
Separate objects apart sequentailly
import pygame as pg class Field: width = 100 height = 100 buffer_right = 10 bugger_top = 10 def __init__(self, position): self.color = (255,0,0) self.image = pg.Surface([self.width, self.height]).convert() self.image.fill(self.color) self.rect = self.image.get_rect(topleft=position) def draw(self, screen): screen.blit(self.image, self.rect) def set_fields(): fields = [] for row in range(4): for col in range(4): #number in row * its width + (buffer), number in col * its hieght + (buffer) field = Field((row*Field.width+(row*Field.buffer_right), col*Field.height+(col*Field.bugger_top))) fields.append(field) return fields pg.init() screen = pg.display.set_mode((800,600)) screen_rect = screen.get_rect() done = False fields = set_fields() while not done: screen.fill((0,0,0)) for event in pg.event.get(): if event.type == pg.QUIT: done = True for field in fields: field.draw(screen) pg.display.update()
Recommended Tutorials:
Reply
#17
Particle Effects
simple particle effects

fire particle effect

import pygame as pg import traceback from random import uniform, choice vec = pg.math.Vector2 vec3 = pg.math.Vector3 BLACK = (0, 0, 0) WHITE = (255, 255, 255) class Custom_color(pg.Color): ''' This is an attempt of creating an object that can be used as a pygame.Color, but also has vector operations. ''' def __init__(self, color): self.vec = vec3(color[0:3]) super().__init__(int(color[0]), int(color[1]), int(color[2])) def update(self): self.r = int(self.vec.x) self.g = int(self.vec.y) self.b = int(self.vec.z) class Game: def __init__(self): pg.init() self.clock = pg.time.Clock() self.screen = pg.display.set_mode((800, 600)) self.screen_rect = self.screen.get_rect() self.fps = 60 self.all_sprites = pg.sprite.Group() try: p_image_strip = pg.image.load('fire_particles_strip.png' ).convert_alpha() self.p_images = [p_image_strip.subsurface(((i * 40, 0), (40, 40))) for i in range(4)] except: # if loading the image fails, create some dummy images self.p_images = [] for i in range(4): surf = pg.Surface((40, 40), pg.SRCALPHA) surf.fill(WHITE) self.p_images.append(surf) def create_particle(self, pos): # create a list of colors for a gradient over time # this looks something like a fire: colors = [ (255, 255, 255), (255, 200, 0), (200, 50, 0), (60, 60, 80) ] # instantiate a paticle with a reference to the particle images # and the list of colors Particle(self, pos, self.p_images, colors) def update(self): # create particles every frame self.create_particle((self.screen_rect.w / 4, self.screen_rect.h - 30)) self.create_particle((self.screen_rect.w / 4 * 3, self.screen_rect.h - 30)) self.all_sprites.update() def draw(self): self.screen.fill(BLACK) for s in self.all_sprites: s.draw(self.screen) pg.display.update() def run(self): self.running = True while self.running: self.clock.tick(self.fps) caption = 'FPS: {} | number of particles: {}'.format( int(self.clock.get_fps()), len(self.all_sprites)) pg.display.set_caption(caption) for event in pg.event.get(): if event.type == pg.QUIT: self.running = False self.update() self.draw() pg.quit() class Particle(pg.sprite.Sprite): def __init__(self, game, pos, images=None, colors=[]): super().__init__() self.game = game self.game.all_sprites.add(self) if images: # if initialized with a list of images, choose one at random self.original_image = choice(self.game.p_images).copy() self.image = self.original_image.copy() self.rect = self.image.get_rect() else: # if not initialized with images, draw a circle self.image = pg.Surface((20, 20)) self.image.set_colorkey((0, 0, 0)) self.rect = self.image.get_rect() pg.draw.ellipse(self.image, (255, 255, 255), self.rect) # make a self.colors = [vec3(x) for x in colors] self.color = Custom_color(self.colors[0]) self.alpha = 255 if len(self.colors) > 1: self.prev_color = vec3(self.colors[0]) self.target_color = vec3(self.colors[1]) self.target_index = 1 self.lerp_dist = 0 self.lerp_speed = 0.05 self.pos = vec(pos) self.rect.topleft = self.pos # set random velocity vector self.vel = vec(uniform(-1, 1), uniform(-5, -1)) def update(self): # add velocity to position self.pos += self.vel # update rect self.rect.topleft = self.pos # reduce alpha gradually self.alpha -= 2 if self.alpha < 0: self.kill() else: self.color.a = int(self.alpha) def draw(self, screen): self.blend_colors() self.image = self.original_image.copy() self.image.fill(self.color, None, pg.BLEND_RGBA_MULT) screen.blit(self.image, self.pos) def blend_colors(self): if len(self.colors) > 1: if self.lerp_dist < 1: # linear interpolation between previous and target color self.color.vec = self.prev_color.lerp(self.target_color, self.lerp_dist) self.color.update() self.lerp_dist += self.lerp_speed else: # if lerp distance reached 1, set the next target color self.target_index += 1 if self.target_index < len(self.colors): self.prev_color = self.target_color self.target_color = self.colors[self.target_index] self.lerp_dist = 0 if __name__ == '__main__': try: g = Game() g.run() except Exception: traceback.print_exc() pg.quit()
Recommended Tutorials:
Reply
#18
RPG map making and loading
Orthogonal map (top-down) loading from spritesheet. This repo shows a small example of using PyTMX to load tmx files generated from Tiled Editor.

Tiled is a map editor to easily place your sprites by hand and allocated collision positions, etc. PyTMX loads these maps. The repo provided includes PyTMX with it and has a predefined tmx map. It shows a small simple example of these libraries combined together to make a map and a character colliding with it.

main.py is file to run in this directory. It is the main game loop and loads the level created and player to move around. As coded: the player is colored red in grass, and blue when a collision is detected when it would be out of bounds.
Recommended Tutorials:
Reply
#19
Basic multiline text

import pygame as pg import pygame.freetype def main(): pg.init() screen = pg.display.set_mode((400, 600)) clock = pg.time.Clock() # define the font size and spacing fontsize = 36 margin_x = 10 # pixels from the left margin_y = 10 # pixels from the top spacing_y = 4 # pixels between lines # initialize a font (Arial) font = pygame.freetype.SysFont('Arial', fontsize) # a sample string with line breaks sample_text = ('This is the first line.\n' + 'This is the second line.\n' + 'This is the third line.\n\n' + 'This is the fifth line.') # create a list from the string and render it to surfaces rendered_fonts =[] for i, line in enumerate(sample_text.split('\n')): txt_surf, txt_rect = font.render(line, pg.Color('black')) # set the text rect to a position based on the line number and # spacing parameters txt_rect.topleft = (margin_x, margin_y + i * (fontsize + spacing_y)) rendered_fonts.append((txt_surf, txt_rect)) # main loop running = True while running: for event in pg.event.get(): if event.type == pg.QUIT: running = False # draw the text screen.fill(pg.Color('white')) for txt_surf, txt_rect in rendered_fonts: screen.blit(txt_surf, txt_rect) clock.tick(60) pg.display.flip() pg.quit() if __name__ == '__main__': main()
Recommended Tutorials:
Reply
#20
Space Invaders (player and player's shots)

import pygame as pg pg.init() class Laser: def __init__(self, loc): self.image = pg.Surface((5,40)).convert() self.image.fill((255,255,0)) self.rect = self.image.get_rect(center=loc) self.speed = 5 def update(self): self.rect.y -= self.speed def render(self, surf): surf.blit(self.image, self.rect) class Player: def __init__(self, screen_rect): self.screen_rect = screen_rect #self.image = pg.image.load('spaceship.png').convert() self.image = pg.Surface([50,50]) #to avoid loading an image self.image.fill((0,0,255)) #to avoid loading an image #self.image.set_colorkey((255,0,255)) #if loading an image, settings colorkey for it self.transformed_image = pg.transform.rotate(self.image, 180) #if image, rotate it start_buffer = 300 self.rect = self.image.get_rect( center=(screen_rect.centerx, screen_rect.centery + start_buffer) ) self.dx = 300 self.lasers = [] def get_event(self, event): if event.type == pg.KEYDOWN: if event.key == pg.K_SPACE: self.lasers.append(Laser(self.rect.center)) def update(self, keys, dt): self.rect.clamp_ip(self.screen_rect) if keys[pg.K_LEFT]: self.rect.x -= self.dx * dt elif keys[pg.K_RIGHT]: self.rect.x += self.dx * dt for laser in self.lasers: laser.update() def draw(self, surf): for laser in self.lasers: laser.render(surf) surf.blit(self.transformed_image, self.rect) screen = pg.display.set_mode((800,600)) screen_rect = screen.get_rect() player = Player(screen_rect) clock = pg.time.Clock() done = False while not done: keys = pg.key.get_pressed() for event in pg.event.get(): if event.type == pg.QUIT: done = True player.get_event(event) screen.fill((0,0,0)) delta_time = clock.tick(60)/1000.0 player.update(keys, delta_time) player.draw(screen) pg.display.update()
Recommended Tutorials:
Reply


User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020
This forum uses Lukasz Tkacz MyBB addons.
Forum use Krzysztof "Supryk" Supryczynski addons.