Pourquoi mes couilles collent? [fermé]

je fais un clone de Ballz,un jeu mobile où vous devez tirer un tas entier de balles sur les blocs qui se cassent après plusieurs coups. C'est comme BrickBreaker sous stéroïdes. Ça marche, mais je ne sais pas tirer sur les couilles. Je sais d'après les tests qu'au moment du tir, les balles sont à des endroits différents, mais immédiatement après ils occupent le même espace.

Oh btw, le chemin que je suis en les gardant séparés est de faire les boules aller plus loin à l'extérieur de l'écran. Donc vous pouvez l'imaginer comme les configurer tous l'un derrière l'autre, hors écran, en dessous du bas du lecteur.

Voici mon code:

import pygame
import math
import random
from vector import *

backgroundColor = (0, 0, 0)
ballColor = (255, 255, 255)

sizeOfOneBlock = 50.0
realDimension = 600.0
blockNumberInLine = int(realDimension/sizeOfOneBlock)
size = [int(realDimension), int(realDimension)]

# eg. probability(1/3)
def probability(chance):
    return random.random() <= chance

def abs(x):
    if x>=0:
        return x
    else:
        return -x

# the classes used:
# Block, BlockHandler, Ball, Player

class Block():
    def __init__(self, strength, i, j):
        self.strength = strength
        # i and j are numbers between 0 and blockNumberInLine-1
        self.i, self.j = i, j
        self.refreshStats()

    def refreshStats(self):
        self.color = (100, 224, 89)

    def display(self, Surface):
        pygame.draw.rect(Surface, (0, 0, 255), (self.i*sizeOfOneBlock, self.j*sizeOfOneBlock, sizeOfOneBlock, sizeOfOneBlock), 0)

class BlockHandler():
    def __init__(self):
        self.blockList = []
        self.blockPositions = []

    def resetPositionArray(self):
        self.blockPositions = []
        for block in self.blockList:
            self.blockPositions.append([block.i*sizeOfOneBlock, block.j*sizeOfOneBlock])

    def addNewLayer(self, gameLevel):
        # move every existing block down
        for block in self.blockList:
            block.j += 1
        # add new layer
        for i in range(blockNumberInLine):
            if probability(1/3):
                # gameLevel determines the strength of the block
                self.blockList.append(Block(gameLevel, i, 0))
        # after all blocks are loaded, do this
        self.resetPositionArray()

    def displayBlocks(self, Surface):
        for block in self.blockList:
            block.display(Surface)

class Ball():
    def __init__(self, posVector, moveVector):
        self.posVector = posVector
        self.moveVector = moveVector
        self.radius = 2
        self.x = int(self.posVector.x)
        self.y = int(self.posVector.y)

    def move(self):
        self.posVector.add(self.moveVector)
        self.x = int(self.posVector.x)
        self.y = int(self.posVector.y)

    def display(self, Surface):
        pygame.draw.circle(Surface, ballColor, (self.x, self.y), self.radius)

    def changeDirection(self, tuple):
        # east
        if tuple[0]>0:
            self.moveVector.x = abs(self.moveVector.x)
        # west
        if tuple[0]<0:
            self.moveVector.x = -abs(self.moveVector.x)
        # south
        if tuple[1]>0:
            self.moveVector.y = abs(self.moveVector.y)
        # north
        if tuple[1]<0:
            self.moveVector.y = -abs(self.moveVector.y)

    def collisionDetect(self, blockX, blockY, blockSize, circleX, circleY, circleRadius):
        xDeflect, yDeflect = 0, 0

        # if in the same column
        if (circleX>=blockX) and (circleX<=(blockX+blockSize)):
            # if touching block from above or below
            distance = circleY-(blockY+0.5*blockSize)
            if abs(distance)<=(0.5*blockSize+circleRadius):
                # either 1 or -1
                if distance!=0:
                    yDeflect = distance/abs(distance)
        # if in the same row
        if (circleY>=blockY) and (circleY<=(blockY+blockSize)):
            # if touching block from left or right
            distance = circleX-(blockX+0.5*blockSize)
            if abs(distance)<=(0.5*blockSize+circleRadius):
                if distance!=0:
                    xDeflect = distance/abs(distance)

        return [xDeflect, yDeflect]

    def checkForCollisions(self, blockPositions):
        # walls
        if (self.x<=(0+self.radius)):
            # east
            self.changeDirection([1,0])
        if (self.x>=(realDimension-self.radius)):
            # west
            self.changeDirection([-1,0])
        if (self.y<=(0+self.radius)):
            # south
            self.changeDirection([0,1])

        # blocks
        for pos in blockPositions:
            collision = self.collisionDetect(pos[0], pos[1], sizeOfOneBlock, self.x, self.y, self.radius)
            self.changeDirection(collision)

class Player():
    def __init__(self, posVector):
        self.posVector = posVector
        self.x = int(self.posVector.x)
        self.y = int(self.posVector.y)

        self.level = 1
        self.numberOfBalls = 3
        self.balls = []

    def resetBalls(self):
        self.balls = []
        for j in range(self.numberOfBalls):
            self.balls.append(Ball(self.posVector, moveVector=Vector(0.0, 0.0)))
            # print(ball)

    def placeBalls(self, separateVector):
        # self.resetBalls()
        for j in range(len(self.balls)):
            ball = self.balls[j]
            for i in range(j):
                ball.posVector.subtract(separateVector)

    def display(self, Surface):
        # possibly change color
        pygame.draw.circle(Surface, ballColor, (self.x, self.y), 20)

    def displayBalls(self, Surface):
        for ball in self.balls:
            ball.display(Surface)

    def updateBalls(self, blockHandler):
        for ball in self.balls:
            ball.move()
            ball.checkForCollisions(blockPositions=blockHandler.blockPositions)

def main():
    pygame.init()
    screen = pygame.display.set_mode(size)
    pygame.display.set_caption("Ballz")
    done = False
    clock = pygame.time.Clock()

    blockHandler = BlockHandler()
    blockHandler.addNewLayer(1)

    playerPosition = Vector(realDimension/2, realDimension-10)
    player = Player(posVector=playerPosition)
    player.resetBalls()

    # -------- Main Program Loop -----------
    while not done:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True

            if event.type == pygame.KEYDOWN:
                # JFF
                if event.key == pygame.K_w:
                    blockHandler.addNewLayer(1)

                # for debugging
                if event.key == pygame.K_d:
                    for ball in player.balls:
                        print(ball.posVector.x, ball.posVector.y)
                        print(ball.moveVector.x, ball.moveVector.y)
                        print("")
                if event.key == pygame.K_r:
                    player.resetBalls()

            if event.type == pygame.MOUSEBUTTONUP:
                mousePos = pygame.mouse.get_pos()
                player.shootVector = Vector(mousePos[0]-player.x, mousePos[1]-player.y).shortenTo(1)

                for ball in player.balls:
                    for i in range(player.balls.index(ball)*10):
                        ball.posVector.subtract(player.shootVector)
                    ball.moveVector = player.shootVector

                    # test
                    print(ball.posVector.x, ball.posVector.y)
                    print(ball.moveVector.x, ball.moveVector.y)
                    print("")

        # LOGIC
        player.updateBalls(blockHandler)

        # DRAW
        screen.fill(backgroundColor)

        blockHandler.displayBlocks(screen)
        player.displayBalls(screen)
        player.display(screen)

        pygame.display.flip()
        # 60 frames per second
        clock.tick(60)

    pygame.quit()

if __name__ == "__main__":
    main()

Edit: Oublié d'ajouter la classe vector.

class Vector():
    def __init__(self, x=0, y=0):
        self.x, self.y = x, y

    def magnitude(self):
        return ((self.x)**2 + (self.y)**2)**0.5

    def shortenTo(self, radius):
        magnitude = self.magnitude()
        unitX = self.x/magnitude
        unitY = self.y/magnitude

        return Vector(unitX*radius, unitY*radius)

    def add(self, addedVector):
        self.x += addedVector.x
        self.y += addedVector.y

    def subtract(self, subtractedVector):
        self.x -= subtractedVector.x
        self.y -= subtractedVector.y

    def printCoordinates(self):
        print(self.x, self.y)
9
demandé sur Shiv Bhatia 0000-00-00 00:00:00

1 réponses

Désolé, pas de reproduction, vos couilles vont bien: enter image description here

Non, mais le problème que vous avez est avec des objets mutables. Lorsque vous définissez

ball.moveVector = player.shootVector

vous définissez tous moveVector's vers le même objet, ainsi chaque détection de collision changera la direction de toutes les balles simultanément. La plus simple correctif:

ball.moveVector = player.shootVector + Vector(x=0, y=0)

EDIT

j'ai utilisé un autre vector module, dans votre cas, vous pouvez soit utiliser copy.copy ou créer un personnalisé __add__ méthode:

def __add__(self, other):
    if not isinstance(other, Vector)
        raise ValueError
    return Vector(self.x+other.x, self.y+other.y)

(Ce qui vient à l'intérieur du Vector classe, de même pour soustraction et mult.)

END EDIT

il y a aussi quelques problèmes avec la façon dont vous réinitialisez lorsque les balles quittent l'image et vous devriez empêcher le joueur de cliquer à nouveau jusqu'à ce que les balles sont réinitialisées, mais je suppose que cela vient dans le développement plus tard.

Annexe

Note: je travaille en Python 3 et soit j'ai installé un vector module, ou ils ont changé beaucoup de choses, j'ai donc dû modifier certains de la syntaxe. Espérons que cela aide :)

import pygame
import math
import random
from vector import *

backgroundColor = (0, 0, 0)
ballColor = (255, 255, 255)

sizeOfOneBlock = 50.0
realDimension = 600.0
blockNumberInLine = int(realDimension/sizeOfOneBlock)
size = [int(realDimension), int(realDimension)]

# eg. probability(1/3)
def probability(chance):
    return random.random() <= chance

def abs(x):
    if x>=0:
        return x
    else:
        return -x

# the classes used:
# Block, BlockHandler, Ball, Player

class Block():
    def __init__(self, strength, i, j):
        self.strength = strength
        # i and j are numbers between 0 and blockNumberInLine-1
        self.i, self.j = i, j
        self.refreshStats()

    def refreshStats(self):
        self.color = (100, 224, 89)

    def display(self, Surface):
        pygame.draw.rect(Surface, (0, 0, 255), (self.i*sizeOfOneBlock, self.j*sizeOfOneBlock, sizeOfOneBlock, sizeOfOneBlock), 0)

class BlockHandler():
    def __init__(self):
        self.blockList = []
        self.blockPositions = []

    def resetPositionArray(self):
        self.blockPositions = []
        for block in self.blockList:
            self.blockPositions.append([block.i*sizeOfOneBlock, block.j*sizeOfOneBlock])

    def addNewLayer(self, gameLevel):
        # move every existing block down
        for block in self.blockList:
            block.j += 1
        # add new layer
        for i in range(blockNumberInLine):
            if probability(1/3):
                # gameLevel determines the strength of the block
                self.blockList.append(Block(gameLevel, i, 0))
        # after all blocks are loaded, do this
        self.resetPositionArray()

    def displayBlocks(self, Surface):
        for block in self.blockList:
            block.display(Surface)

class Ball():
    def __init__(self, posVector, moveVector):
        self.posVector = posVector
        self.moveVector = moveVector
        self.radius = 2
        self.x = int(self.posVector['x'])
        self.y = int(self.posVector['y'])

    def move(self):
        self.posVector += self.moveVector
        self.x = int(self.posVector['x'])
        self.y = int(self.posVector['y'])

    def display(self, Surface):
        pygame.draw.circle(Surface, ballColor, (self.x, self.y), self.radius)

    def changeDirection(self, tuple):
        # east
        if tuple[0]>0:
            self.moveVector['x'] = abs(self.moveVector['x'])
        # west
        if tuple[0]<0:
            self.moveVector['x'] = -abs(self.moveVector['x'])
        # south
        if tuple[1]>0:
            self.moveVector['y'] = abs(self.moveVector['y'])
        # north
        if tuple[1]<0:
            self.moveVector['y'] = -abs(self.moveVector['y'])

    def collisionDetect(self, blockX, blockY, blockSize, circleX, circleY, circleRadius):
        xDeflect, yDeflect = 0, 0

        # if in the same column
        if (circleX>=blockX) and (circleX<=(blockX+blockSize)):
            # if touching block from above or below
            distance = circleY-(blockY+0.5*blockSize)
            if abs(distance)<=(0.5*blockSize+circleRadius):
                
7
répondu