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)
1 réponses
Désolé, pas de reproduction, vos couilles vont bien:
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):