Pages

joi, 30 mai 2019

PyGame : First interface - part 10.

Today I will create a maze can be used into pygame interface gaming area.
The algorithm starts at a random cell.
Mark the current cell as visited, and get a list of its neighbors.
Now, for each neighbor, starting with a randomly selected neighbor.
If that neighbor hasn't been visited, remove the wall between this cell and that neighbor.
Use this recourse idea with that neighbor as the current cell.
Let's see the source code:
import os
import pygame
from pygame.locals import *
from random import choice
# create a maze cell with rect sized 6 pixels
class maze_cell(pygame.sprite.Sprite):
    w, h = 6, 6

    def __init__(self, x, y, maze):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface([self.w, self.h])
        self.image.fill((0, 0, 255))
        self.rect = self.image.get_rect()
        self.rect.x = x * self.w
        self.rect.y = y * self.h

        self.x = x
        self.y = y
        self.maze = maze
        self.nbs = [(x + nx, y + ny) for nx, ny in ((-2, 0), (0, -2), (2, 0), (0, 2))
                    if 0 <= x + nx < maze.w and 0 <= y + ny < maze.h]
    # draw screen with pygame blit 
    def draw(self, screen):
        screen.blit(self.image, self.rect)
# create the maze wall 
class maze_wall(maze_cell):
    def __init__(self, x, y, maze):
        super(maze_wall, self).__init__(x, y, maze)
        self.image.fill((0, 0, 0))
        self.type = 0
# create the maze by generate into grid 
class create_maze:
    def __init__(self, size):
        self.w, self.h = size[0] // maze_cell.w, size[1] // maze_cell.h
        self.grid = [[maze_wall(x, y, self) for y in range(self.h)] for x in range(self.w)]

    def get(self, x, y):
        return self.grid[x][y]

    def place_maze_wall(self, x, y):
        self.grid[x][y] = maze_wall(x, y, self)

    def draw(self, screen):
        for row in self.grid:
            for maze_cell in row:
                maze_cell.draw(screen)

    def generate(self, screen=None, animate=False):
        
        unvisited = [c for r in self.grid for c in r if c.x % 2 and c.y % 2]
        cur = unvisited.pop()
        stack = []

        while unvisited:
            try:
                n = choice([c for c in map(lambda x: self.get(*x), cur.nbs) if c in unvisited])
                stack.append(cur)
                nx, ny = cur.x - (cur.x - n.x) // 2, cur.y - (cur.y - n.y) // 2
                self.grid[nx][ny] = maze_cell(nx, ny, self)
                self.grid[cur.x][cur.y] = maze_cell(cur.x, cur.y, self)
                cur = n
                unvisited.remove(n)

                if animate:
                    self.draw(screen)
                    pygame.display.update()
                    pygame.time.wait(10)
            except IndexError:
                if stack:
                    cur = stack.pop()

def draw_maze(screen):
    maze = create_maze(WINSIZE)
    maze.generate(screen, True)

WINSIZE = (maze_cell.w * 76, maze_cell.h * 76)

def main():
    pygame.init()
    screen = pygame.display.set_mode(WINSIZE)
    pygame.display.set_caption('Generate maze')
    screen.fill((0, 0, 0))
    clock = pygame.time.Clock()

    draw_maze(screen)

    done = 0

    while not done:
        for e in pygame.event.get():
            if e.type == QUIT or (e.type == KEYUP and e.key == K_ESCAPE):
                done = 1
        pygame.display.update()
        clock.tick()

if __name__ == '__main__':
    main()
The result of this source code:

marți, 28 mai 2019

PyGame : First interface - part 9.

Today I start with another tutorial with pygame python module and python version 3.7.3.
For this series of tutorials, I will introduce you a radar interface.
The advantages of using such an interface are evident from technical considerations and not only. This type of interface is very used in games because most users have become accustomed to it.
Let's start installing the pygame python module.
C:\Python373\Scripts>pip install pygame
Requirement already satisfied: pygame in c:\python373\lib\site-packages (1.9.6)
I try to follow some goals, like:
  • install pygame with pip tool for python 3.7.3;
  • create an interface for drawing;
  • use a configuration with values, see: screen_size;
  • use events to stop the script;
  • use line and circle with math and radians;
  • use the pygame.gfxdraw module to draw lines and circles;
This python script is simple to understand:
import pygame
import math
from pygame.locals import *
import pygame.gfxdraw

configuration = {
        'screen_size': (500,500),
}
pygame.init()
screen = pygame.display.set_mode(configuration['screen_size'])
FPSCLOCK = pygame.time.Clock()
done = False
screen.fill((0, 0, 0))
azimuth_degrees=0
while not done:
    screen.fill(0)
    # get events
    for e in pygame.event.get():
        if e.type == QUIT or (e.type == KEYDOWN and e.key == K_ESCAPE):
            done = True
            break
    screen.fill((0, 0, 0))
    # radar position on window     
    radar = (250,250)
    # radar lenght 
    radar_len = 276
    for x in range(1, 250, 30):
        # radar circle position on window
        pygame.gfxdraw.circle(screen,radar[0],radar[1],x,(0,0,255))   

    # calculate the x and y radar beam
    x = radar[0] + math.cos(math.radians( azimuth_degrees)) * radar_len
    y = radar[1] + math.sin(math.radians( azimuth_degrees)) * radar_len
    
    # then render the line radar with value (x,y)
    pygame.gfxdraw.line(screen, radar[0],radar[1], int(x),int(y), Color("blue"))
    pygame.display.flip() 

      
    azimuth_degrees+=1
    FPSCLOCK.tick(40)