0

Ive asked this question before and I was told that the mask requires a position for it to correctly detect collisions. With that advice I was able to modify the code so that it works properly. However the first frame of the laser activation will remove asteroids that it shouldnt be touching. Ive looked at other questions and am still confused

# Written by: Theo
# Date: December 2020 - July 2021
#
# Version 1: an endless runner game where the player
# controls a ship traveling through space, dodging obstacles


import pygame
import math
import time
import random
import RiftObstacles



global ship
global rot_ship
global shipX
global moonMask

pygame.init()
FPS = 100
clock = pygame.time.Clock()
size = pygame.display.Info()
WIDTH = 1000
HEIGHT = 1000
pygame.display.set_caption('Parallax Nebula')
screen = pygame.display.set_mode((WIDTH, HEIGHT))


########## Rift Variables
ship = pygame.image.load("Images/Rift/Ship.PNG")
ship = pygame.transform.scale(ship, (85, 125))
rot_ship = ship
shipX = 450
shipY = 700


A1 = pygame.image.load("Images/Rift/Asteroids/1.PNG")
A1 = pygame.transform.scale(A1, (100, 100))
A1 = pygame.Surface.convert_alpha(A1)

A2 = pygame.image.load("Images/Rift/Asteroids/2.PNG")
A2 = pygame.transform.scale(A2, (100, 100))
A2 = pygame.Surface.convert_alpha(A2)

A3 = pygame.image.load("Images/Rift/Asteroids/3.PNG")
A3 = pygame.transform.scale(A3, (100, 100))
A3 = pygame.Surface.convert_alpha(A3)

A4 = pygame.image.load("Images/Rift/Asteroids/4.PNG")
A4 = pygame.transform.scale(A4, (100, 100))
A4 = pygame.Surface.convert_alpha(A4)

A5 = pygame.image.load("Images/Rift/Asteroids/5.PNG")
A5 = pygame.transform.scale(A5, (100, 100))
A5 = pygame.Surface.convert_alpha(A5)

A6 = pygame.image.load("Images/Rift/Asteroids/6.PNG")
A6 = pygame.transform.scale(A6, (100, 100))
A6 = pygame.Surface.convert_alpha(A6)

A7 = pygame.image.load("Images/Rift/Asteroids/7.PNG")
A7 = pygame.transform.scale(A7, (100, 100))
A7 = pygame.Surface.convert_alpha(A7)

A8 = pygame.image.load("Images/Rift/Asteroids/8.PNG")
A8 = pygame.transform.scale(A8, (100, 100))
A8 = pygame.Surface.convert_alpha(A8)

A9 = pygame.image.load("Images/Rift/Asteroids/9.PNG")
A9 = pygame.transform.scale(A9, (100, 100))
A9 = pygame.Surface.convert_alpha(A9)

A10 = pygame.image.load("Images/Rift/Asteroids/10.PNG")
A10 = pygame.transform.scale(A10, (100, 100))
A10 = pygame.Surface.convert_alpha(A10)

A11 = pygame.image.load("Images/Rift/Asteroids/11.PNG")
A11 = pygame.transform.scale(A11, (100, 100))
A11 = pygame.Surface.convert_alpha(A11)

A12 = pygame.image.load("Images/Rift/Asteroids/12.PNG")
A12 = pygame.transform.scale(A12, (60, 100))
A12 = pygame.Surface.convert_alpha(A12)

F1 = pygame.image.load("Images/Rift/Fuel/1.PNG")
F1 = pygame.transform.scale(F1, (150, 150))

F2 = pygame.image.load("Images/Rift/Fuel/2.PNG")
F2 = pygame.transform.scale(F2, (150, 150))

F3 = pygame.image.load("Images/Rift/Fuel/3.PNG")
F3 = pygame.transform.scale(F3, (150, 150))

F4 = pygame.image.load("Images/Rift/Fuel/4.PNG")
F4 = pygame.transform.scale(F4, (150, 150))

F5 = pygame.image.load("Images/Rift/Fuel/5.PNG")
F5 = pygame.transform.scale(F5, (150, 150))

F6 = pygame.image.load("Images/Rift/Fuel/6.PNG")
F6 = pygame.transform.scale(F6, (150, 150))

comet = pygame.image.load("Images/Rift/Comet.PNG")
comet = pygame.transform.scale(comet, (80, 250))


moon = pygame.image.load("Images/Rift/Moon - WIP.PNG")
moon = pygame.transform.smoothscale(moon, (1200, 1200))
moon = pygame.Surface.convert_alpha(moon)
moonMask = pygame.mask.from_surface(moon)

angle = 0
lasers = []
stretch = []
for i in range(60):
    laserImg = pygame.image.load("Images/Rift/Laser/"+str(i+1)+".PNG")
    laserImg = pygame.Surface.convert_alpha(laserImg)
    stretchTemp = int(15*math.cos(math.pi*i/30))
    stretch.append(50 - stretchTemp)
    laserImg = pygame.transform.scale(laserImg, (50-stretchTemp, 1050))
    lasers.append(laserImg)



angle = 0

RiftBG = pygame.image.load("Images/Rift/Background/BG.PNG")
RiftBG = pygame.Surface.convert_alpha(RiftBG)
RiftBG = pygame.transform.smoothscale(RiftBG, (1000, 1000))





#Transparent comet warning
def warning(surface, color, rect):
    shape_surf = pygame.Surface(pygame.Rect(rect).size, pygame.SRCALPHA)
    pygame.draw.rect(shape_surf, color, shape_surf.get_rect())
    surface.blit(shape_surf, rect)
    
#Moving the ship 
def moveShip(shipX, X, angle):
    if (X >= 0 and shipX > 100) or (X <= 0 and shipX < 800):
        shipX -= X    
    else:
        shipX -= X
        angle -= (X*speed)/11
        
                
    rot_ship = pygame.transform.rotate(ship, angle)
    return(shipX, rot_ship, angle)

#Pulling ship towards the middle of the screen
def riftpull(shipX, angle, rot_ship):
    if shipX < 440:
        if angle > -25:
            angle -= 0.1 * speed
        else:
            angle += 0.1 * speed
        shipX, rot_ship, angle = moveShip(shipX, (angle/2.5), angle)
                
    elif shipX > 460:
        if angle < 25:
            angle += 0.1 * speed
        else:
            angle -= 0.1 * speed
        shipX, rot_ship, angle = moveShip(shipX, (angle/2.5), angle)
    
    elif 440 < shipX < 460:
        if abs(angle) > 1:
            angle = angle/1.2
        else:
            angle = 0
        shipX, rot_ship, angle = moveShip(shipX, (angle/2.5), angle)
    return shipX, angle, rot_ship  


#Ship Travel through the rift    
def rift():
    global ship
    global rot_ship
    global shipX
    global speed
    global moon
    global moonOutline
    global moonMask
    global distance
    speed = 5
    angle = 0
    laserOn = 2*FPS
    laserAnimation = int(FPS/30)
    laserFrame = 0
    distanceTimer = 0
    delay = FPS
    laserMode = False
    crash = False
    key = pygame.key.get_pressed()
    wallX = 470
    wallY = [-1000, -3000]
    
    
    rocks = [A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12]
    fuel = [F1, F2, F3, F4, F5, F6]
    numRock, rockX, rockY, numComet, cometX, cometY, numMoon, moonX, moonY, moonScale, numFuel, fuelX, fuelY = RiftObstacles.path()
    rockType = []
    rockAngle = []  
    rockAngle2 = []
    rockRot = []
    for i in range(numRock):
        rockType.append(random.choice(rocks))
        rockAngle.append(random.uniform(-0.2,0.2))
        rockAngle2.append(rockAngle[i])

    fuelType = []
    fuelAngle = []
    fuelAngle2 = []
    fuelRot = []
    for i in range(numFuel):
        fuelType.append(random.choice(fuel))
        fuelAngle.append(random.uniform(-0.2,0.2))
        fuelAngle2.append(fuelAngle[i])
        
    warningWidth = []
    for i in range(numComet):
        warningWidth.append(10)

    endRift = False
    while endRift == False:
        screen.blit(RiftBG, (0,0))
           
        #Displaying obstacles       
        for i in range(numRock):
            rockRot.append(pygame.transform.rotate(rockType[i], rockAngle2[i]))
            screen.blit(rockRot[i], (rockX[i], rockY[i]))

        for i in range(numComet):
            screen.blit(comet, (cometX[i], cometY[i]))
            if -2000 < cometY[i] < HEIGHT:
                warningHEIGHT = HEIGHT - cometY[i]
                cometWarning = pygame.Rect(cometX[i]+40 - warningWidth[i]/2, cometY[i]+100, warningWidth[i], warningHEIGHT)
                if warningWidth[i] < 78:
                    warningWidth[i] += 1.5
                warning(screen, (250, 200, 3, 127), (cometWarning))

        for i in range(numFuel):
            fuelRot.append(pygame.transform.rotate(fuelType[i], fuelAngle2[i]))
            screen.blit(fuelRot[i], (fuelX[i], fuelY[i]))
        

        if laserMode == True:
            laserOn -= 1
            if laserOn <= 0:
                laserMode = False

            rot_laser = pygame.transform.rotate(lasers[laserFrame], angle)
            laserAnimation -= 1
            if -1 < laserAnimation < 1:
                laserAnimation = FPS/30
                if laserFrame < 59:
                    laserFrame += 1
            laserRect = rot_laser.get_rect()
            if angle == 0:
                correction = 50*math.sin((angle*math.pi)/180)
                laserRect.midbottom = (shipX + 42 - correction, shipY+100)
                
            elif angle <= 1:
                correction = angle*9
                laserRect.midbottom = (shipX + 50 - correction, shipY+100)
            
            else:
                correction = angle*7
                laserRect.midbottom = (shipX + 30 - correction, shipY+100)
                
            screen.blit(rot_laser, laserRect)
                
        if laserMode == False:
            laserOn = 180
            laserFrame = 0
            
        for i in range(numMoon):
            moon = pygame.transform.smoothscale(moon, (int(100*moonScale[i]), int(100*moonScale[i])))
            screen.blit(moon, (moonX[i], moonY[i]))
            
    



        
        #Ship Movement                
        screen.blit(rot_ship, (int(shipX), shipY))
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT or event.key == pygame.K_a:
                    key = 'left'
                elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
                    key = 'right'

                #Activating the laser
                elif event.key == pygame.K_SPACE:
                    if laserMode == False:
                        laserMode = True
                    
                else:
                    key = 'up'
                    
            if event.type == pygame.KEYUP:
                key = 'up'

        if key == 'left':
            if angle < 35 and shipX > 50:
                angle += 0.2*speed
                
            shipX, rot_ship, angle = moveShip(shipX, (angle/2.5), angle)

        elif key == 'right':
            if angle > -35 and shipX < 850:
                angle -= 0.2*speed
                
            shipX, rot_ship, angle = moveShip(shipX, (angle/2.5), angle)
            
        elif key == 'up':
            shipX, angle, rot_ship = riftpull(shipX, angle, rot_ship)


        #Collision detection
        shipRect = pygame.Rect(shipX, shipY, 85, 125)
        shipMask = pygame.mask.from_surface(rot_ship)
        if laserMode == True:
            rot_laser = pygame.transform.rotate(lasers[laserFrame], angle)
            if angle == 0:
                correction = 50*math.sin((angle*math.pi)/180)
                laserRect.midbottom = (shipX + 42 - correction, shipY+100)
                
            elif angle <= 1:
                correction = angle*9
                laserRect.midbottom = (shipX + 50 - correction, shipY+100)
            
            else:
                correction = angle*7
                laserRect.midbottom = (shipX + 30 - correction, shipY+100)
            laserMask = pygame.mask.from_surface(rot_laser)
            
        remove = []
        for i in range(numRock):
            rockRect = pygame.Rect(rockX[i], rockY[i], 100, 100)
            if laserMode == True:
                if rockRect.colliderect(laserRect):
                    rockMask = pygame.mask.from_surface(rockRot[i])
                    offset_x = laserRect.x - rockRect.x
                    offset_y = laserRect.y - rockRect.y
                    laserHit = rockMask.overlap(laserMask, (offset_x, offset_y))
                    if laserHit:
                        remove.append(i)


            
            if rockRect.colliderect(shipRect):
                rockMask = pygame.mask.from_surface(rockRot[i])
                offset_x = shipRect.x - rockRect.x
                offset_y = shipRect.y - rockRect.y
                crash = rockMask.overlap(shipMask, (offset_x, offset_y))
                
        for i in range(len(remove)):
                numRock -= 1
                rockX.pop(remove[i])
                rockY.pop(remove[i])
                rockType.pop(remove[i])
                rockAngle.pop(remove[i])
                rockAngle2.pop(remove[i])
                rockRot.pop(remove[i])
                
        remove = []                    
        for i in range(numComet):
            cometRect = pygame.Rect(cometX[i], cometY[i], 80, 250)
            if cometRect.colliderect(shipRect):
                cometMask = pygame.mask.from_surface(comet)
                offset_x = shipRect.x - cometRect.x
                offset_y = shipRect.y - cometRect.y
                crash = cometMask.overlap(shipMask, (offset_x, offset_y))

        remove = []        
        for i in range(numMoon):
            moonRect = pygame.Rect(moonX[i], moonY[i], int(100*moonScale[i]), int(100*moonScale[i]))
            if int(50*moonScale[i]+60)**2 >= ((shipX+40 - moonX[i]-int(50*moonScale[i]))**2 + (shipY+100 - moonY[i]-int(50*moonScale[i]))**2) and not crash:
                moonMask = pygame.mask.from_surface(moon)
                offset_x = shipRect.x - moonRect.x
                offset_y = shipRect.y - moonRect.y
                crash = moonMask.overlap(shipMask, (offset_x, offset_y))

        remove = []
        for i in range(numFuel):
            fuelRect = pygame.Rect(fuelX[i], fuelY[i], 100, 100)
            if fuelRect.colliderect(shipRect):
                fuelMask = pygame.mask.from_surface(fuelRot[i])
                offset_x = shipRect.x - fuelRect.x
                offset_y = shipRect.y - fuelRect.y
                fuelHit = fuelMask.overlap(shipMask, (offset_x, offset_y))
                if fuelHit:
                    remove.append(i)
                
        for i in range(len(remove)):
            numFuel -= 1
            fuelX.pop(remove[i])
            fuelY.pop(remove[i])
            fuelType.pop(remove[i])
            fuelAngle.pop(remove[i])
            fuelAngle2.pop(remove[i])
            fuelRot.pop(remove[i])
            
        remove = []           
        #Moves objects down screen
        rockRot = []
        fuelRot = []
        for i in range(numRock):
            rockY[i] += speed
            rockAngle2[i] += rockAngle[i]

        for i in range(numMoon):
            moonY[i] += speed
                
        for i in range(numComet):
            cometY[i] += speed * 5
            if cometY[i] > HEIGHT:
                 warningWidth[i] = 10

        for i in range(numFuel):
            fuelY[i] += speed
            fuelAngle2[i] += fuelAngle[i]


        
                
        #Choosing a new path      
        rockPassed = HEIGHT+1
        cometPassed = HEIGHT+1
        moonPassed = HEIGHT+1
        if len(rockY) != 0:
            rockPassed = rockY[-1]
        if len(cometY) != 0:
            cometPassed = cometY[-1]
        if len(moonY) != 0:
            moonPassed = moonY[-1]
        if rockPassed > HEIGHT and cometPassed > HEIGHT and moonPassed > HEIGHT:
            numRock, rockX, rockY, numComet, cometX, cometY, numMoon, moonX, moonY, moonScale, numFuel, fuelX, fuelY = RiftObstacles.path()
            rockType = []
            rockAngle = []
            rockAngle2 = []
            rockRot = []
            fuelType = []
            fuelAngle = []
            fuelAngle2 = []
            fuelRot = []
            for i in range(numRock):
                rockType.append(random.choice(rocks))
                rockAngle.append(random.uniform(-0.2,0.2))
                rockAngle2.append(rockAngle[i])

            for i in range(numFuel):
                fuelType.append(random.choice(fuel))
                fuelAngle.append(random.uniform(-0.2,0.2))
                fuelAngle2.append(fuelAngle[i])

                
            warningWidth = []
            for i in range(numComet):
                warningWidth.append(10)

        #Shows that collision between the ship works with obstacles
        if crash:
            #print('crash')
            crash = False
            
        pygame.display.update()
        clock.tick(FPS)


distance = 0
active = True
while active:
    rift()

pygame.quit()
Theo
  • 41
  • 3
  • 1
    This is way too bulky a project for me to debug myself, however I would recommend that you draw boxes around all the collision rectangles so you can see where they are. I suspect that the collision rectangle may be misplaced. – CmdCoder858 Jul 10 '21 at 15:21
  • Stack Overflow is not a debugging service.. Please read [How to create a Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) and [How do I ask a good question?](https://stackoverflow.com/help/how-to-ask). – Rabbid76 Jul 10 '21 at 16:53

0 Answers0