0

I create an object:

class Tube(Entity):
    def __init__(self, position):
        super().__init__(
            model = 'quad',
            color = color.white,
            position = position,
            scale = Vec2(0.6,6),
            collider = 'box'

and a ball object:

class Ball(Entity):
def __init__(self, color, position, neuronWeights):
    super().__init__(
        model = 'circle',
        color = color,
        position = position,
        scale = 0.4,
        collider = 'sphere'
    )
    self.tube = 0
    self.speed = 0

def update(self):
    # Move
    self.y -= self.speed*time.dt
    self.speed += 8*time.dt

    # Update tube ID
    if tubes[self.tube].upTube.x +1 <= self.x:
        self.tube += 1
    
    # Get tube coordinates
    tubeX = tubes[self.tube].upTube.x
    tubeY = tubes[self.tube].y_position
    tubeX -= self.x
    tubeY -= self.y

    # Check position
    if self.y <= -4 or self.y >= 4:
        self.disable()
    
    # Hit
    hit_info = self.intersects(ignore=(self,),debug=True)
    if str(hit_info.entity) == 'tube':
        print(hit_info.entities)
        self.disable()

def jump(self):
    self.speed = -4

Then I use the "intersects" method to check the collision:

hit_info = self.intersects(ignore=(self,),debug=True)
if str(hit_info.entity) == 'tube':
    self.disable()

But every time a "ball" pass the "tube" x coordinate (even when the ball is under the tube and doesn't touch it, like the image below) it say they ara intersects. How can I fix it? enter image description here

Here the entire code (I removed only some functions that I had created in my opinion useless to bring back here):

from ursina import *
from random import *
from math import *

app = Ursina()

tubes = []
balls = []
start = True
gen = 1
ballsPerGen = 50
tubeDistance = 4
tubeSpace = 1


class Ball(Entity):
    def __init__(self, color, position, neuronWeights):
        super().__init__(
            model = 'circle',
            color = color,
            collider = 'box',
            position = position,
            scale = 0.4
        )
        self.tube = 0
        self.speed = 0
        self.neuron = Neuron(neuronWeights[0],neuronWeights[1],neuronWeights[2],neuronWeights[3],
                        neuronWeights[4],neuronWeights[5],neuronWeights[6],neuronWeights[7],
                        neuronWeights[8],neuronWeights[9],neuronWeights[10],neuronWeights[11],
                        neuronWeights[12],neuronWeights[13],neuronWeights[14],neuronWeights[15], neuronWeights[16])

    def update(self):
        # Move
        self.y -= self.speed*time.dt
        self.speed += 8*time.dt

        # Update tube ID
        if tubes[self.tube].upTube.x +1 <= self.x:
            self.tube += 1
    
        # Get tube coordinates
        tubeX = tubes[self.tube].upTube.x
        tubeY = tubes[self.tube].y_position
        tubeX -= self.x
        tubeY -= self.y

        # Jump
        jump = self.neuron.jump(tubeX, tubeY)
        if jump == 1:
            self.jump()

        # Check position
        if self.y <= -4 or self.y >= 4:
            self.disable()
    
        # Hit
        hit_info = self.intersects(ignore=(self,),debug=True)
        if str(hit_info.entity) == 'tube':
            print(hit_info.entities)
            self.disable()

    def jump(self):
        self.speed = -4


class Tube(Entity):
    def __init__(self, position):
        super().__init__(
            model = 'quad',
            color = color.white,
            collider = 'box',
            position = position,
            scale = Vec2(0.6,6)
        )
        self.spawn = True

    def update(self):
        self.x -= 2*time.dt

        # Spawn new tube
        if self.y>=2 and self.x<tubeDistance and self.spawn:
            self.spawn = False
            new_tube = Tubes()
            tubes.append(new_tube)


class Tubes():
    def __init__(self):
        self.y_position = uniform(-2,2)
        self.upTube = Tube(Vec2(8,3+tubeSpace+self.y_position))
        self.downTube = Tube(Vec2(8,-(3+tubeSpace)+self.y_position))


class Neuron:
    def __init__(self, ...):
        ...

    def jump(self, tubeX, tubeY):
        # return 1 or 0

def firstGeneration():
    balls = []
    for _ in range(ballsPerGen):
        ball = Ball(randomColor(), Vec2(-5, uniform(-3,3)), initRandomWeights())
        balls.append(ball)
    return balls

def newGeneration(weights):
    balls = []
    for _ in range(ballsPerGen):
        ball = Ball(randomColor(), Vec2(-5, uniform(-3,3)), mutations(weights))
        balls.append(ball)
    return balls

def update():
    global start
    global tubes
    global balls
    global gen
    global lastBall

    if held_keys['space']:
        application.time_scale = 0.1
    else:
        application.time_scale = 1

    # Start
    if start:
        start = False
        tube = Tubes()
        tubes.append(tube)
        balls = firstGeneration()
        print("\nGen 1")

    # New gen
    finish = True
    for ball in balls:
        if ball.enabled == True:
            lastBall = ball
            finish = False
            break

    if finish:
        for tube in tubes:
            tube.upTube.disable()
            tube.downTube.disable()
        tubes = []
        tube = Tubes()
        tubes.append(tube)

        max = 0
        bestBall = balls[0]

        # Best ball
        for ball in balls:
            if ball.tube>max:
                max = ball.tube
                bestBall = ball
    
        print("Best score: ", bestBall.tube)
    
        balls = []
        newWeights = lastBall.neuron.weights
        balls = newGeneration(newWeights)
        gen += 1
        print('\nGen ', gen)


app.run()

1 Answers1

1

It seems you were having some problems with the intersection.

I will comment in code where the problem was:

from ursina import *
from ursina.prefabs import *

app = Ursina()

EditorCamera()



ground = Entity(model='plane', scale = 30, collider='plane')

bird = Entity(model = 'circle',
        color = color.yellow,
        position=(0,10,0),
        scale = 0.4,
        collider = 'sphere'
        )

tube = Entity(model = 'quad',
            color = color.white,
            position = (0,0,0),
            scale = Vec2(20,6),
            collider = 'box'
            )


def update():
    # Hit
    hit_info = bird.intersects(ignore=(),debug=True)


    if hit_info.entity == tube: ## HERE <------------
    # You had if str(hit_info.entity) == 'tube':

        print(hit_info.entities)
        

def input(key):
    if key == 'a':
        bird.y -= 1
app.run()
Lixt
  • 201
  • 4
  • 19
  • If I use the "box" collider with the ball it works, but it wouldn't be appropriate – Lorenzo Zorri Nov 15 '22 at 14:48
  • Sorry. Problem with code. Try it now. – Lixt Nov 16 '22 at 08:28
  • Thanks, but having more tubes I would like to insert the code about intersections directly into the class "ball" (in the update method), wanting to create multiple at the same time. How can I do that? – Lorenzo Zorri Nov 16 '22 at 08:49
  • I added the entire code, so you can better understand what I intend to do – Lorenzo Zorri Nov 16 '22 at 09:08
  • 1
    You could just do `if hit_info.entity in tubes`, ir even `if isinstance(hit_info.entity, Tube)` if you want to check if it intersected any of them. Using str() is wrong regardless. – pokepetter Nov 16 '22 at 10:45