python – PYGAME NÃO É RECONHECIDO NO PYCHARM

Boa noite, gente!

Eu estou com um problema que tá me irritado muito, pois nada resolve.Estou utilizando o pycharm e ele simplesmente não reconhece a biblio pygame. Eu já tentei de tudo, vários comandos no terminal (uso Linux) do próprio site Python, tutoriais brasileiros, gringos da internet, de fórum. Enfim, não sei mais onde caçar ajuda. O erro é “ModuleNotFoundError: No module named ‘pygame’
“. Quando eu utilizei alguns comandos no terminal, pareceu que tudo tava resolvido, mas é só executar o código que acontece isso. Alguém me ajuda porque tenho um jogo pra entregar sexta e não tenho muito tempo até lá kkkk

inserir a descrição da imagem aqui

python – Pygame – RPG Battle-Style Animation and movement when not controlled by player

Examples: https://www.youtube.com/watch?v=C2cOiFntLY4 https://www.youtube.com/watch?v=iHl1YFkeR78

I am making a small little RPG based on a text-adventure game that I made. This RPG involves a battle system similar to the SNES Final Fantasy games. I am currently limited to the player character and a single enemy, since those are the only actors that were ever present in the text-adventure game.

My battle system involves selecting your choice (attack or run away) and, upon attacking, the damage is calculated, battle text is displayed showing the damage, and then there is a short delay before the enemy attacks in return. This is all fine and good, but I don’t want static images of my player and the enemy.

In the first example above, you can see the enemies jump onto the player for their attacks and you can see that the player runs to the enemy and then swings his sword. In the second example, you can see that the players will run forward a short distance and then either cast a spell or swing their weapon. What I’m looking for is something somewhere in the middle — I want my player sprite to run/jump over to a position directly in front of the enemy, perform an attack animation in that position, and then run/jump back to their starting position.

I don’t have my code in front of me, but I do know that I am currently drawing the sprites in specific locations, basically using standard pygame.draw functionality.

So: Any chance someone could walk me through this? I know how to move my player around when outside of the battle system, but I don’t know how to properly do the same thing when the player is not in control… and adding the Y-axis to the equation (for the jump) just stumps me in this situation. I have (extremely basic) knowledge of tweening/easing functions, which I suspect will be relevant here, but I’ve only ever used them along one axis to make an item bounce up and down in place, so I’m not sure how to apply them to a sprite moving in two different axes.

Any help would be appreciated, especially code examples. Thanks!

Por favor me ajude a resumir minhas colisões feitas no pygame

if pos_y == 321 and pos_x == 300 or pos_y == 322 and pos_x == 300:
pos_x += 10
if pos_y == 323 and pos_x == 300 or pos_y == 324 and pos_x == 300:
pos_x += 10
if pos_y == 325 and pos_x == 300 or pos_y == 326 and pos_x == 300:
pos_x += 10
if pos_y == 327 and pos_x == 300 or pos_y == 328 and pos_x == 300:
pos_x += 10
if pos_y == 329 and pos_x == 300 or pos_y == 330 and pos_x == 300:
pos_x += 10

    if pos_y == 331 and pos_x == 300 or pos_y == 332 and pos_x == 300:
        pos_x += 10
    if pos_y == 333 and pos_x == 300 or pos_y == 334 and pos_x == 300:
        pos_x += 10
    if pos_y == 335 and pos_x == 300 or pos_y == 336 and pos_x == 300:
        pos_x += 10
    if pos_y == 337 and pos_x == 300 or pos_y == 338 and pos_x == 300:
        pos_x += 10
    if pos_y == 339 and pos_x == 300 or pos_y == 330 and pos_x == 300:
        pos_x += 10

python – Tic-tac-toe game using Pygame

I programmed a tic-tac-toe game using pygame. It’s the first game I make. I’d really appreaciate any comments you have about the coding style and any improvements that could be made.

import pygame
import graphics # External module graphics.py
import logic    # External module logic.py

# Setting up window
HEIGHT = 600
WIDTH = 480
FPS = 30
TITLE = "Tic-tac-toe"

# Defining colors
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)

# Initializing pygame and create window
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption(TITLE)
clock = pygame.time.Clock()

# Game settings
TOP = 100
SIZE = 450
CELL = SIZE // 3
CPU_SPEED = FPS // 2


class TicTacToe():
    """Main tic-tac-toe game object.

    Attributes
    ----------
    board : graphics.Board
        pygame.Sprite object. Consists mainly of the lines that make
        up the grid.
    board_logic : logic.Board
        Object that defines the game logic and AI.
    cells : 3 x 3 nested list.
        List containing individual graphics.Cell objects.
        Each `Cell` object is a cell sprite.
    player_score : graphics.Text
        Sprite object that shows the player score.
    cpu_score : graphics.Text
        Sprite object that shows the cpu score.
    end_message : graphics.Text
        Sprite object that shows a message when the game ends:
        win/lose/tie.
    player_play : bool
        Determine when it's the player's turn to play.
    check : bool
        Determine when the check the end of the game.
        Set to `True` after each player or cpu move.
    reset : bool
        Determines when to reset the board after the end of game.
    timer : int
        Counter to limit cpu moves speed.
    timer2 : int
        Counter to limit end game reactions speed.

    Methods
    -------
    add_to_group(sprites_group)
        Add all of the sprite objects of the `TicTacToe` object
        to `sprites_group`.
    create_cells(CELL)
        Create 9 `graphics.Cell` objects of size `SIZE` x `SIZE`
        and append them to `self.cells`.
    update()
        Check if the game has ended or a player has won. Calls
        methods accordingly. Verify when to check with `self.check`
        and limit frequency using `self.timer2`.
        Verifies it's the computer's turn to play by checking
        `self.player_turn`. Calls `computer_turn` method when
        corresponds. Limits computer's play speed using
        `self.timer`.
    computer_turn()
        Use `graphics.board_logic.computer_turn()` method to determine
        next case to fill.
        Fill cell accordingly and update to check board end game
        conditions and player's turn.
    reset_game()
        Reset `graphics.Board` to delete extra lines on the board.
        Reset all `graphics.Cell` sprites to a blank surface.
        Reset `self.end_message` to show an empty string.
    update_score()
        Add one point to the corresponding current player score.
        Either `self.cpu_score` or `self.player_score`.
    win_message()
        Modify `self.end_message` to show a win or lose message.
    tie_message()
        Modify `self.end_message` to show a tied game message.
    get_cells():
        Return `self.cells` containing all the `graphics.Cell`
        sprite objects.
    is_player_turn():
        Return `True` when player's turn conditions are met.
        `False` otherwise.
    to_reset():
        Return `self.reset` attribute. Use to determine when
        to reset the game board.

    """

    def __init__(self):
        self.board = graphics.Board()
        self.board_logic = logic.Board()
        self.cells = self.create_cells(CELL)
        self.player_score = graphics.Text('P1 : 0',
                                          (WIDTH * 4 // 5, TOP * 1 // 3))
        self.cpu_score = graphics.Text('CPU : 0',
                                       (WIDTH * 4 // 5, TOP * 2 // 3))
        self.end_message = graphics.Text('',
                                         (WIDTH * 2 // 5, TOP // 2))
        self.player_play = False
        self.check = False
        self.reset = False
        self.timer = 0
        self.timer2 = 0

    def add_to_group(self, sprites_group):
        sprites_group.add(self.player_score)
        sprites_group.add(self.cpu_score)
        sprites_group.add(self.end_message)
        for cell in self.cells:
            sprites_group.add(cell)
        sprites_group.add(self.board)

    def create_cells(self, CELL=CELL):
        cells = ()
        for i in range(3):
            row = ()
            for j in range(3):
                pos = (self.board.rect.left + j * CELL,
                       self.board.rect.top + i * CELL)
                row.append(graphics.Cell(pos))
            cells.append(row)
        return cells

    def update(self):
        if self.check:
            if self.timer2 > CPU_SPEED // 2:
                self.timer2 = 0
                self.check = False
                if self.board_logic.check_winner():
                    self.board.draw_triple(self.board_logic.win_line_pos())
                    self.win_message()
                    self.update_score()
                    self.reset = True
                elif self.board_logic.endgame():
                    self.tie_message()
                    self.reset = True
            else:
                self.timer2 += 1

        if self.timer < CPU_SPEED:
            self.timer += 1
        else:
            self.timer = 0
            if not self.is_player_turn() and not self.to_reset():
                self.computer_turn()

    def computer_turn(self):
        i, j = self.board_logic.computer_turn()
        # print(self.board_logic)
        self.cells(i)(j).computer_fill()
        self.check = True
        self.player_play = True

    def player_turn(self, ij):
        self.timer = 0
        self.board_logic.user_turn(ij)
        i, j = ij
        self.cells(i)(j).player_fill()
        self.player_play = False
        self.check = True

    def reset_game(self):
        self.board.new_board()
        self.board_logic.reset()
        self.end_message.write('')
        for i in range(3):
            for j in range(3):
                self.cells(i)(j).reset()
        self.reset = False

    def update_score(self):
        if self.board_logic.current_player() == 'o':
            self.player_score.add1()
        else:
            self.cpu_score.add1()

    def win_message(self):
        if self.board_logic.current_player() == 'o':
            self.end_message.write('You win!')
        else:
            self.end_message.write('You lose!')

    def tie_message(self):
        self.end_message.write('     Tie!')

    def get_cells(self):
        return self.cells

    def is_player_turn(self):
        return self.player_play and not self.board_logic.check_winner()

    def to_reset(self):
        return self.reset


all_sprites = pygame.sprite.Group()
game = TicTacToe()
game.add_to_group(all_sprites)

# Game loop
running = True
while running:
    clock.tick(FPS)

    # Process input
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.MOUSEBUTTONUP:
            if game.to_reset():
                game.reset_game()
            elif game.is_player_turn():
                pos = pygame.mouse.get_pos()
                cells = game.get_cells()
                for i in range(3):
                    for j in range(3):
                        if cells(i)(j).hits(pos):
                            game.player_turn((i, j))

    game.update()

    # Draw / render
    screen.fill(BLACK)
    all_sprites.draw(screen)
    pygame.display.flip()

pygame.quit()

I separated the code in different modules. The graphics module includes the classes to create the different sprites used by the game (the game board, the board cells and the text messages).
The logic module is used for the computer AI.

I’m sharing only this “game part” of the code because this is where I’d appreciate your comments. If you’d like to check the other modules or get them in order to play the game, you can do it here.

Thank you very much for your time.

python – Collision Detection without Coordinates in Tilemaps in Pygame

So if I wan’t to make a collision detection with rectangles, than I can just do this as I have the coordinates of the rectangle:

rcx = 200
rcy = 200
rcw = 200
rch = 100
plx = 500
ply = 450
plw = 50
plh = 50
rectcolor = (100, 150, 200)

testobj = pygame.draw.rect(win, rectcolor, (rcx, rcy, rcw, rch))
player = pygame.draw.rect(win, (150, 200, 100), (plx, ply, plw, plh))
    if plx <= rcx + rcw and plx + plw >= rcx and ply <= rcy + rch and ply + plh >= rcy:
    rectcolor = (50, 100, 50)
else:
    rectcolor = (100, 150, 200)

Ok, good! I made a collision detection with rectangles because I know the coordinates of the rectangles. (I don’t think this is the most efficient way but it works)
Anyways
I am programming a Bomberman game, right now I don’t have any sprites but I use rectangles for it.
This is my code:

import pygame

pygame.init()

WinWidth = 800
WinHeight = 608
p1x = 32
p1y = 32
vel = 1
clock = pygame.time.Clock()

win = pygame.display.set_mode((WinWidth, WinHeight))

def player():
    pygame.draw.rect(win, (0, 200, 200), (p1x, p1y, 32, 32))

class invi:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        pygame.draw.rect(win, (0, 255, 200), (x, y, 32, 32))


class Wall:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        pygame.draw.rect(win, (50, 50, 50), (x, y, 32, 32))


class Breakable:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        pygame.draw.rect(win, (200, 150, 100), (x, y, 32, 32))


game_map1 = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
             (0, 10, 10, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 10, 10, 0),
             (0, 10, 0, 2, 0, 2, 0, 2, 0, 0, 0, 2, 0, 2, 0, 2, 0, 10, 0),
             (0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0),
             (0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0),
             (0, 2, 2, 2, 2, 10, 10, 2, 2, 10, 2, 2, 10, 10, 2, 2, 2, 2, 0),
             (0, 2, 0, 2, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 2, 0, 2, 0),
             (0, 2, 2, 2, 2, 2, 0, 2, 2, 10, 2, 2, 0, 2, 2, 2, 2, 2, 0),
             (0, 2, 0, 2, 0, 2, 0, 2, 10, 10, 10, 2, 0, 2, 0, 2, 0, 2, 0),
             (0, 0, 0, 2, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2, 2, 0, 0, 0),
             (0, 2, 0, 2, 0, 2, 0, 2, 10, 10, 10, 2, 0, 2, 0, 2, 0, 2, 0),
             (0, 2, 2, 2, 2, 2, 0, 2, 2, 10, 2, 2, 0, 2, 2, 2, 2, 2, 0),
             (0, 2, 0, 2, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 2, 0, 2, 0),
             (0, 2, 2, 2, 2, 10, 10, 2, 2, 10, 2, 2, 10, 10, 2, 2, 2, 2, 0),
             (0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0),
             (0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0),
             (0, 10, 0, 2, 0, 2, 0, 2, 0, 0, 0, 2, 0, 2, 0, 2, 0, 10, 0),
             (0, 10, 10, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 10, 10, 0),
             (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))

run = True
while run:

    pygame.init()

    clock.tick(100)
    win.fill((0, 255, 200))
    y = 0
    for layer in game_map1:
        x = 0
        for tile in layer:
            if tile == 0:
                Wall(x * 32, y * 32)
            if tile == 10:
                invi(x * 32, y * 32)
            if tile == 2:
                Breakable(x * 32, y * 32)
            x += 1
        y += 1

    player()

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            run = False
    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_d:
            p1x += vel
        elif event.key == pygame.K_a:
            p1x -= vel

    pygame.display.update()

sooo… I watched a tutorial and even tried to make a collision detection on my own. But I just can’t do it. I don’t have coordinates for the rectangles in the tilemap and there are very much rectangles in the tilemap, too. How could you make a collision detection with a tilemap with no coordinates and many rectangles? And yeah, the game doesn’t have much stuff going un ’til now… oh and I deleted the parts where I tried to make a collision detection as they all were bad, didn’t work, took up much of the place and just made the whole code more confusing.

Btw if this is not a good question to ask in this StackExchange Q&A Website, sorry, im new to this Website. But I would still be happy to get an answer on this question! 🙂

movement – Any ideas as to how a role playing game collision can be made in pygame WITHOUT the use of sprites

Thanks for contributing an answer to Game Development Stack Exchange!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

Use MathJax to format equations. MathJax reference.

To learn more, see our tips on writing great answers.

python – Optimizing performance of randomly generated pygame maze game (as well as other possible feedback)

I made a random maze generator that is also playable. The performance is crap and I’d like to improve it. I’ll be working on this for a few more days to make it run better myself, but just thought I’d leave this here if people want to help. (Will still be active on this post)

Any and all feedback is appreciated, though my main goal for now is performance optimization. I am aware that my code is bad.

import random, sys, time, pygame
from fractions import gcd
from pygame.locals import *
from random import *

#End goal: Make a random labyrinth generator
#Generate random, completable walls

    #Have generate_maze be actually completable (Atm moves before assigning, which creates a lot of problems when moving out of already assigned tiles)

#This is stolen. Credit to John Millikin from stackoverflow.com and john-millikin.com. I'd never come up with a solution this compact
def gcd(a, b):
    while b:
        a, b = b, a%b
    return a

if input('Would you like to enable blind mode (recommended)? y/n >>> ') == 'y':
    blind_mode = True
else: blind_mode = False
tile_amount_multiplier = 1 #!!! NEVER SET ABOVE 2! IF YOU DO, THE RESULTS ARE TOTALLY INTENTIONAL GAME DESIGN THAT I JUST DON'T WANT YOU TO SEE
pygame.init()
window_resolution = 800, 600
window = pygame.display.set_mode((window_resolution(0), window_resolution(1)))
score = 0
stag_line_width = 5
line_width = stag_line_width
tile_width_height = gcd(window_resolution(0), window_resolution(1)) // 4 // tile_amount_multiplier
touched = ()
wall_drawn = False
player_posx = 0
player_posy = 0
border = window_resolution(0)//100 *2 * tile_amount_multiplier -1, window_resolution(1)//100 *2 * tile_amount_multiplier -1
goal_posx = randint(0, border(0))
goal_posy = randint(0, border(1))
player_pos = player_posx, player_posy
goal_pos = goal_posx, goal_posy
keys = pygame.key.get_pressed()
tile_amount = window_resolution(0) // tile_width_height * (window_resolution(1) // tile_width_height)

def is_border(coordinates, direction):
    if direction == 'right':
        if coordinates(0) >= border(0):
            return True
        else:
            return False
    elif direction == 'left':
        if coordinates(0) <= 0:
            return True
        else: 
            return False
    elif direction == 'up':
        if coordinates(1) <= 0:
            return True
        else:
            return False
    elif direction == 'down':
        if coordinates(1) >= border (1):
            return True
        else: 
            return False
    else:
        print('You are safe from the end of the fucking world')
        return False
    print('Unexpected error in determining border location. You should probably fix that')

def is_wall(dire):
    if is_border(player_pos, dire) == False:
        for pos in no_wall_tiles:
            if (dire == 'right' or 'left') and ((player_pos(1) == pos(0)(1)) or (player_pos(1) == pos(1)(1))):
                if dire == 'right':
                    if ((player_pos(0) == pos(0)(0)) or (player_pos(0) == pos(1)(0))) and (((player_pos(0) + 1) == pos(1)(0)) or ((player_pos(0) + 1) == pos(0)(0))):
                        return False
                elif dire == 'left':
                    if ((player_pos(0) == pos(0)(0)) or (player_pos(0) == pos(1)(0))) and (((player_pos(0) - 1) == pos(1)(0)) or ((player_pos(0) - 1) == pos(0)(0))):
                        return False
            if (dire == 'up' or 'down') and ((player_pos(0) == pos(1)(0)) or (player_pos(0) == pos(0)(0))):
                if dire == 'up':
                    if ((player_pos(1) == pos(0)(1)) or (player_pos(1) == pos(1)(1))) and (((player_pos(1) - 1) == pos(1)(1)) or ((player_pos(1) - 1) == pos(0)(1))):
                        return False
                elif dire == 'down':
                    if ((player_pos(1) == pos(0)(1)) or (player_pos(1) == pos(1)(1))) and (((player_pos(1) + 1) == pos(1)(1)) or ((player_pos(1) + 1) == pos(0)(1))):
                        return False
        return True
    else:
        return True

def random_direction():
    digit = randint(1, 4)
    if digit == 1:
        return 'right'
    if digit == 2:
        return 'left'
    if digit == 3:
        return 'up'
    return 'down'


def generate_maze():
    wall_generated = False
    generation_visited = ()
    global no_wall_tiles
    no_wall_tiles = ()
    generation_pos = (randint(0, border(0)), randint(0, border (1)))
    generation_last_pos = ()
    first_run = True
    while wall_generated == False:
        if tuple(generation_pos) in generation_visited:
            is_visited = True
        else:
            is_visited = False
        if is_visited == False:
            generation_visited.append(tuple(generation_pos))
            if first_run == False:
                no_wall_tiles.append((tuple(generation_last_pos), tuple(generation_pos)))
        direction = random_direction()
        generation_last_pos = generation_pos.copy()
        if is_border(tuple(generation_pos), direction) == False: #Checks for bounds
            if direction == 'right': #Checks every direction possible
                generation_last_pos = generation_pos.copy()
                generation_pos(0) += 1
            elif direction == 'left': # ^
                generation_last_pos = generation_pos.copy()
                generation_pos(0) -= 1
            elif direction == 'up': # ^
                generation_last_pos = generation_pos.copy()
                generation_pos(1) -= 1
            elif direction == 'down': # ^
                generation_last_pos = generation_pos.copy()
                generation_pos(1) += 1
        first_run = False
        if len(generation_visited) == tile_amount:
            print(no_wall_tiles)
            wall_generated = True

def is_touched(x):
    return x in touched

def draw_walls():
    opposite_cord = 0
    line_color = 100, 0 , 100
    if blind_mode == True:
        line_color = 0,0,0
    for z in range(window_resolution(0) // tile_width_height):
        global line_width
        coordinatex = window_resolution(0) // 10
        coordinatey = window_resolution(1) // 10
        posx = 0
        for x in range(coordinatex // 10 * 4 * tile_amount_multiplier):
            for i in range(1, 4):
                if i == 1:
                    for coord in no_wall_tiles:
                        if (x, z) in coord and (x, z+1) in coord:
                            should_draw = False
                            break
                        should_draw = True
                    if should_draw == True:
                        pygame.draw.line(window,(line_color),(posx, opposite_cord + tile_width_height), (tile_width_height + posx, opposite_cord + tile_width_height), line_width)
                elif i == 2:
                    for coord in no_wall_tiles:
                        if (x, z) in coord and (x+1, z) in coord:
                            should_draw = False
                            break
                        should_draw = True
                    if should_draw == True:
                        pygame.draw.line(window,(line_color),(posx + tile_width_height, opposite_cord), (posx + tile_width_height, opposite_cord + tile_width_height), line_width)
            posx += tile_width_height
            line_width = stag_line_width
        for y in range(coordinatey // 10 * 4 * tile_amount_multiplier):
            posx += tile_width_height
            line_width = stag_line_width
        opposite_cord += tile_width_height
        posx = 0

def is_victory ():
    if player_pos == goal_pos:
        return True
    return False

def draw_tileset():
    opposite_cord = 0
    for z in range(window_resolution(0) // tile_width_height):
        global line_width
        rect_color = 0,0,0
        rect_coror_perma = rect_color
        coordinatex = window_resolution(0) // 10
        coordinatey = window_resolution(1) // 10
        posx = 0
        for x in range(coordinatex // 10 * 4 * tile_amount_multiplier):
            if goal_posx == x and goal_posy == z:
                line_width = 0
                rect_color = (255, 0, 0)
            elif player_posx == x and player_posy == z:
                rect_color = (0, 0, 255)
                line_width = 0
            elif is_touched((x, z)):
                rect_color = 50,200,200
                line_width = 0
            pygame.draw.rect(window, rect_color, (posx, opposite_cord, tile_width_height, tile_width_height), line_width)
            rect_color = rect_coror_perma
            posx += tile_width_height
            line_width = stag_line_width
        for y in range(coordinatey // 10 * 4 * tile_amount_multiplier):
            if player_posy == z and player_posy == y:
                line_width = 1
            pygame.draw.rect(window,(rect_color),(opposite_cord, posx, tile_width_height, tile_width_height), line_width)
            posx += tile_width_height
            line_width = stag_line_width
        opposite_cord += tile_width_height
        posx = 0

#Dumb ass system to coordinates conversion guide: coord main_coordinate = main_coordinate, secondary coordinate = z

generate_maze()
draw_tileset()
draw_walls()
pygame.display.update()

while True:
    player_pos = player_posx, player_posy
    if is_victory() == True:
        score += 1
        print('Your score is now', score)
        player_posx = 0
        player_posy = 0
        goal_posx = randint(0, border(0))
        goal_posy = randint(0, border(1))
        goal_pos = goal_posx, goal_posy
        touched = ()
        generate_maze()
        window.fill((0, 0, 0))
        draw_tileset()
        draw_walls()
        pygame.display.update()
    for event in pygame.event.get():
        if event.type == QUIT:
            print('You got a score of', score)
            pygame.quit()
            sys.exit()
        if event.type == pygame.KEYDOWN:
            if event.key == K_a and is_wall('left') == False:
                if player_pos not in touched:
                    touched.append(player_pos)
                player_posx -= 1
                window.fill((0, 0, 0))
                draw_tileset()
                draw_walls()
                pygame.display.update()
            elif event.key == K_d and is_wall('right') == False:
                if player_pos not in touched:
                    touched.append(player_pos)
                player_posx += 1 
                window.fill((0, 0, 0))
                draw_tileset()
                draw_walls()
                pygame.display.update()
            elif event.key == K_s and is_wall('down') == False:
                if player_pos not in touched:
                    touched.append(player_pos)
                player_posy += 1
                window.fill((0, 0, 0))
                draw_tileset()
                draw_walls()
                pygame.display.update()
            elif event.key == K_w and is_wall('up') == False:
                if player_pos not in touched:
                    touched.append(player_pos)
                player_posy -= 1
                window.fill((0, 0, 0))
                draw_tileset()
                draw_walls()
                pygame.display.update()

Implementing collision system using Separate Axis Theorem (SAT) in Pygame

so let me preface this by saying that I am only moderately experienced with Python and pygame. With that being said, I wanted to implement a collision system using SAT so my player could collide with rotated rectangles. I have created code that will take the local coordinates of the rectangle and apply a rotation matrix so I can get the world coordinates of the rotated rectangle. Here is that code, it works pretty well.

def getRotation(angle):
    angle = np.radians(angle)
    return np.array(
        (
            (np.cos(angle), -np.sin(angle), 0),
            (np.sin(angle), np.cos(angle), 0),
            (0, 0, 1),
        )
    )


def getTranslation(Tx, Ty):
    return np.array(((1, 0, Tx), (0, 1, Ty), (0, 0, 1)))


def getWorldCoord(points, Tx, Ty, angle):
    transMat = getTranslation(Tx, Ty)
    rotMat = getRotation(angle)
    A = transMat @ rotMat @ np.linalg.inv(transMat)
    for i in range(points.shape(0)):
        A.dot(points(i, :))

    points_world = A.dot(points.T)
    return points_world


Now, my issue is implementing SAT and also getting the player to stop when collided (that is, finding the Minimum translation vector or MTV). And this is the part I am struggling with. The collision bool turns True when it gets close to the rectangle but not hitting. The MTV also has this odd behavior where it sort of bounces off the rectangle very unnaturally. I wanted it in such a way that the rotated rectangle behaves like a solid wall. Any help on this would be greatly appreciated, I’ve been at this for almost a week now.

Here is the code for my SAT collision system.

def normalize(v):
    norm = np.sqrt(v(0) ** 2 + v(1) ** 2)
    return (v(0) / norm, v(1) / norm)


def arrayToVector(p):
    vecs = ()
    for i in range(p.shape(0)):
        vecs.append((p(0)(i), p(1)(i)))
    return vecs


def dot(a, b):
    return a(0) * b(0) + a(1) * b(1)


def orthogonal(v):
    return (v(1), -v(0))


def edge_direction(p0, p1):
    return (p1(0) - p0(0), p1(1) - p1(0))


def vertices_to_edges(vertices):
    return (
        edge_direction(vertices(i), vertices((i + 1) % len(vertices)))
        for i in range(len(vertices))
    )


def project(vertices, axis):
    dots = (dot(vertex, axis) for vertex in vertices)
    return (min(dots), max(dots))


def contains(n, range_):
    a = range_(0)
    b = range_(1)
    if b < a:
        a = range_(1)
        b = range_(0)
    return (n >= a) and (n <= b)


def overlap(a, b):
    if contains(a(0), b) or contains(a(1), b) or contains(b(0), a) or contains(b(1), a):
        return True
    return False


# region (SAT_coll_fxn)
# def SAT_collision(vertices_a, vertices_b):
#     edges_a = vertices_to_edges(vertices_a)
#     edges_b = vertices_to_edges(vertices_b)
#     proj_a = (float("inf"), float("-inf"))
#     proj_b = (float("inf"), float("-inf"))
#     overlap_val = float("inf")

#     edges = edges_a + edges_b

#     axes = (normalize(orthogonal(edge)) for edge in edges)

#     for i in range(len(axes)):
#         proj_a = project(vertices_a, axes(i))
#         proj_b = project(vertices_b, axes(i))
#         overlapping = overlap(proj_a, proj_b)
#         overlap_val = min(proj_a(1), proj_b(1)) - max(proj_a(0), proj_b(0))
#         if not overlapping:
#             return False
#     return True
# endregion


class SAT_Collision:
    def __init__(self, poly1, poly2):
        self.poly1 = poly1
        self.poly2 = poly2
        self.collide = False
        self.overlap_val = float("inf")

    def collision_dect(self):
        edges_a = vertices_to_edges(self.poly1)
        edges_b = vertices_to_edges(self.poly2)
        edges = edges_a + edges_b
        axes = (normalize(orthogonal(edge)) for edge in edges)

        for i in range(len(axes)):
            proj_a = project(self.poly1, axes(i))
            proj_b = project(self.poly2, axes(i))
            overlapping = overlap(proj_a, proj_b)
            self.overlap_val = min(proj_a(1), proj_b(1)) - max(proj_a(0), proj_b(0))
            if not overlapping:
                return False

        d = vec()

        return True

Here is my main loop. I have my MTV code commented out temporarily.

rect1 = Rectangle(10, 10, 50, 30)
rect2 = pg.Rect(100, 100, 10, 100)
rectangle_dragging = False

w = rect2.width
h = rect2.height
Tx = rect2.left
Ty = rect2.top
x0 = Tx
y0 = Ty
angle = 333.44
points = np.array(((x0, y0, 1), (x0 + w, y0, 1), (x0, y0 + h, 1), (x0 + w, y0 + h, 1)))
rect_coor = getWorldCoord(points, Tx, Ty, angle)
rect_coor_vec = arrayToVector(rect_coor)
rect_center = rect2.centerx

line_coor = ((200, 200), (100, 100))

collision_font = pg.font.Font(None, 30)
collision_message = "collided!"
collision_render = collision_font.render(collision_message, True, BLACK)
collision_text_rect = collision_render.get_rect()
collision_text_rect.center = (WIDTH - 100, HEIGHT - 100)


# - mainloop -

clock = pg.time.Clock()

running = True

while running:
    screen.fill(LIGHTGREY)
    surf = pg.Surface(rect2.size).convert_alpha()

    # - events -

    for event in pg.event.get():
        if event.type == pg.QUIT:
            running = False

        elif event.type == pg.MOUSEBUTTONDOWN:
            if event.button == 1:
                if rect1.rect.collidepoint(event.pos):
                    rectangle_dragging = True
                    mouse_x, mouse_y = event.pos
                    offset_x = rect1.rect.x - mouse_x
                    offset_y = rect1.rect.y - mouse_y

        elif event.type == pg.MOUSEBUTTONUP:
            if event.button == 1:
                rectangle_dragging = False

        elif event.type == pg.MOUSEMOTION:
            if rectangle_dragging:
                mouse_x, mouse_y = event.pos
                rect1.rect.x = mouse_x + offset_x
                rect1.rect.y = mouse_y + offset_y

    # - updates (without draws) -
    player_coor = (
        (rect1.rect.left, rect1.rect.top),
        (rect1.rect.right, rect1.rect.top),
        (rect1.rect.left, rect1.rect.bottom),
        (rect1.rect.right, rect1.rect.bottom),
    )
    collision_ob = SAT_Collision(player_coor, rect_coor_vec)
    collision_chk = collision_ob.collision_dect()
    overlap_val = collision_ob.overlap_val

    if collision_chk:
        screen.blit(collision_render, collision_text_rect)
        # d = vec(rect2.left - rect1.rect.left, rect2.top - rect1.rect.top)
        # s = np.sqrt(d.x * d.x + d.y * d.y)
        # rect1.rect.left -= 10 * d.x / s
        # rect1.rect.top -= 10 * d.y / s

    # empty

    # - draws (without updates) -

    pg.draw.rect(surf, (RED), rect2)

    rotSurf = pg.transform.rotate(surf, angle)

    screen.blit(rotSurf, (Tx, Ty))
    pg.draw.rect(screen, BLUE, rect1)
    # pg.draw.line(screen, RED, line_coor(1), line_coor(0), 3)
    # pg.draw.rect(screen, RED, rect2)
    pg.display.flip()
    rect_center = rect2.center
    rect_coor = getWorldCoord(points, Tx, Ty, angle)

    # - constant game speed / FPS -

    clock.tick(FPS)


# - end -

pg.quit()


Here is an image of the results. Note that this is a test environment just to try out the code. I didn’t want to alter the real game code.

Collision bool turned True even though it is not colliding. It only does this when its close.

Thanks!

python – Simple image editor using PyGame

I have recently build a simple image editor in python. There is nothing specific that I am dissatisfied about regarding this code. I am just asking for general criticism to help me improve

import pygame
import random
import time

x = input("Do you want to edit an image?")

if  x == "yes":
    image_url = input("please enter image url")
    image = pygame.image.load(image_url) 
    i_edit = True

else:
    i_edit = False



pygame.init()


red = (255,0,0)
orange = (255,165,0)
yellow = (255,255,0)
green = (0,255,0)
blue = (0,0,215)
indigo = (75,0,130)
violet = (128,0,128)
black = (0, 0, 0)
white = (255,255,255)

gameDisplay = pygame.display.set_mode((900, 900))
clock = pygame.time.Clock()

color = white

crashed = False
buttpressed = 0
rightkeypressed = False
radius = 10

background_colour = (0,0,0)
gameDisplay.fill(background_colour)

if i_edit:
    gameDisplay.blit(image, (0, 0))

while not crashed:

    if radius < 5:
        radius = 5
 
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            crashed = True

        pygame.display.set_caption("Your Pen Size is {0}".format(radius))

        if event.type == pygame.KEYDOWN and rightkeypressed is True:
            if event.unicode == 'n':
                background_colour = black
            if event.unicode == 'w':
                background_colour = white
            if event.unicode == 'r':
                background_colour = red
            if event.unicode == 'o':
                background_colour = orange
            if event.unicode == 'y':
                background_colour = yellow
            if event.unicode == 'g':
                background_colour = green
            if event.unicode == 'b':
                background_colour = blue
            if event.unicode == 'i':
                background_colour = indigo
            if event.unicode == 'p':
                background_colour = violet
            if event.unicode == 'e':
                color = background_colour
            gameDisplay.fill(background_colour)
            if event.unicode == 'q':
                gameDisplay.blit(image, (0, 0))


        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 3:
                rightkeypressed = True

        if event.type == pygame.MOUSEBUTTONUP:
            if event.button == 3:
                rightkeypressed = False
        
        if event.type == pygame.KEYDOWN:
            if event.unicode == 'n':
                color = black
            if event.unicode == 'w':
                color = white
            if event.unicode == 'r':
                color = red
            if event.unicode == 'o':
                color = orange
            if event.unicode == 'y':
                color = yellow
            if event.unicode == 'g':
                color = green
            if event.unicode == 'b':
                color = blue
            if event.unicode == 'i':
                color = indigo
            if event.unicode == 'p':
                color = violet
            if event.unicode == 'e':
                color = background_colour
            if event.unicode == '=':
                radius += 5
            if event.unicode == '-':
                radius -= 5

        
        if event.type == pygame.MOUSEBUTTONDOWN:
            buttpressed += 1


        if event.type == pygame.MOUSEMOTION and (buttpressed%2) != 0:
            pygame.draw.circle(gameDisplay, color, pygame.mouse.get_pos(), radius)

    pygame.display.update()
    clock.tick(60)

2D Platformer Physics (Pygame) – Game Development Stack Exchange

Thanks for contributing an answer to Game Development Stack Exchange!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

Use MathJax to format equations. MathJax reference.

To learn more, see our tips on writing great answers.