1

I am trying to make my battery be able to shoot our directly from the spaceship but right now, its shooting on the left of the spaceship. Does anyone know how to fix this? I was also wondering if anyone knew how to fix my other mistake because whenever I turn the spaceship in certain directions, the battery doesn't switch directions as well but I have the code for it written down.

#Importing packages and intializing pygame 
import os
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d, %d" %(20, 20)
import pygame
pygame.init()
import random
import math
SIZE = (width, height) = (1000, 700) #Screen Size
screen = pygame.display.set_mode(SIZE)

#Defining Colours
GREEN = (0,255,0)
BLACK = (0,0,0)
GREY = (48,48,48)
WHITE = (255, 255, 255)
YELLOW = (246, 255, 112)
BLUE = (0, 0, 255)
RED = (255, 0, 0)

#numFile = open("leaderboard.dat", "r") #Reading file

#=== initialize Variables ===
in_game = False
shipEats = 0
lives = 3
xp = 0

#Ship
x_ship_pos = 500 # ship x coord
y_ship_pos = 600 # ship y coord
x_ship_speed = 0 # move ship x coord by x
y_ship_speed = 0 # move ship y coord by y
direction = 360 #Ship faces up

#Battery
is_battery_on_screen = False
x_battery_pos = 0
y_battery_pos = 0
battery_direction = "UP"

#Evil Battery
x_evilbat_pos = random.randint(0,1000)
y_evilbat_pos = random.randint(0, 700)

#---EWASTE---
xWastePos = random.randint(0,1000)
yWastePos = random.randint(0, 700)

#LOADING ALL IMAGES FOR GAME
backgroundImage = pygame.image.load("spaceBackground.jpg")
mainscreenImage = pygame.image.load("galaxyy.jpg")
shipImage = pygame.image.load("spaceship.png")
batteryImage = pygame.image.load("battery.png")
ewasteImage = pygame.image.load("ewaste.png")
evilbatImage = pygame.image.load("evilbattery.png")

#Functions

def drawScene(screen, mx, my, button): #Draws screen with space background
    screen.blit(backgroundImage, (0,0))

def drawScene2(screen, mx, my, button): #Draws black screen
    screen.fill(BLACK)

def add_athlete(): #Adding a athlete record
    name = input("Please enter your game name")
    score = input("Please enter your game score")
    nameList.append(name),
    scoreList.append(score)

def display_main_screen(): #MAIN SCREEN IN PYGAME
    screen.blit(mainscreenImage, (0,0))   

    leaderBtn = pygame.Rect(30, 550, 300,120) #Leaderboard Button
    pygame.draw.rect(screen, BLUE, leaderBtn)
    leaderBtn = font3.render("Leaderboard", 1, WHITE)
    screen.blit(leaderBtn, (50,590,400,100)) #Displays Text    

    instrBtn = pygame.Rect(350, 550, 300,120) #How to play Button
    pygame.draw.rect(screen, BLUE, instrBtn)
    instrBtn = font3.render("How to play", 1, WHITE)
    screen.blit(instrBtn, (380,590,400,100)) #Displays Text

    quitBtn = pygame.Rect(670, 550, 300,120) #Quit Button
    pygame.draw.rect(screen, BLUE, quitBtn)
    quitBtn = font3.render("Quit", 1, WHITE)
    screen.blit(quitBtn, (760,590,400,100)) #Displays Text 

    playBtn = pygame.Rect(280, 410, 450,120) #Play Game Button
    pygame.draw.rect(screen, BLUE, playBtn)
    playBtn = font.render("Play", 1, WHITE)
    screen.blit(playBtn, (440,440,400,100)) #Displays Text   

def gamePage(): #Game page
    drawScene(screen, mx, my, button) #Draws a new screen
    resetShip()

    score = font2.render("Score: " + str(shipEats), 1, WHITE) #Shows the score on top left corner
    screen.blit(score, (0,0))    


def instrPage(): #How to play page
    drawScene2(screen, mx, my, button)

    mainMenuBtn = pygame.Rect(870, 20, 120,30) #Back to main menu button
    pygame.draw.rect(screen, BLUE, mainMenuBtn)
    mainMenuBtn = font2.render("Main menu", 1, WHITE)
    screen.blit(mainMenuBtn, (875,25,400,100)) #Displays Text

    instr = font2.render("Objective --> Destroy as much e-waste as possible", 1, WHITE)
    screen.blit(instr, (10,20))
    instr = font2.render("Use the arrow keys to move the spaceship up, down, right or left", 1, WHITE)
    screen.blit(instr, (10,70))
    instr = font2.render("Press space to shoot batteries", 1, WHITE)
    screen.blit(instr, (10,120))
    instr = font2.render("Press W to shoot a beam to destroy the big batteries", 1, WHITE)
    screen.blit(instr, (10,170))
    instr = font2.render("Remember to collect all the stars (BLUE DOTS) after destroying e-waste!", 1, WHITE)
    screen.blit(instr, (10,220)) 
    instr = font2.render("Don't touch the e-waste", 1, WHITE)
    screen.blit(instr, (10,270))
    instr = font2.render("You only get one life, USE IT WISELY", 1, WHITE)
    screen.blit(instr, (10,320))
    instr = font2.render("Press esc to return to main menu when playing game", 1, WHITE)
    screen.blit(instr, (10,370))   

def leaderPage(): #Leaderboard page
    drawScene2(screen, mx, my, button)

    mainMenuBtn = pygame.Rect(870, 20, 120,30) #Back to main menu button
    pygame.draw.rect(screen, BLUE, mainMenuBtn)
    mainMenuBtn = font2.render("Main menu", 1, WHITE)
    screen.blit(mainMenuBtn, (875,25,400,100)) #Displays Text 

#-----------DRAWING ALL OBJECTS FOR GAME-----------

def draw_ship(): 
    global shipImage, direction
    # VR - using a different variable, so that every time through here we remember the direction of the original
    newImage = pygame.transform.rotate(shipImage, direction)
    screen.blit(pygame.transform.scale(newImage, (100, 100)), (x_ship_pos, y_ship_pos)) #SPACESHIP  

def draw_explosivebattery(): 
    if is_battery_on_screen: 
        newImage = pygame.transform.rotate(batteryImage, direction)
        screen.blit(pygame.transform.scale(batteryImage, (30, 40)), (x_battery_pos, y_battery_pos)) #BATTERY THAT SHOOTS 

def drawEwaste(): #Piles of e-waste displaying in game 
    global xWastePos, yWastePos
    screen.blit(pygame.transform.scale(ewasteImage, (340, 150)), (xWastePos, yWastePos)) #EWASTE
    yWastePos += 15 #Speed of e-waste yPos
    if yWastePos > height: #Makes e-waste generate randomly from the top going vertically down
        xWastePos = random.randint(0, 500)
        yWastePos = 0
    return

if xWastePos < 0 or xWastePos > 1000 or yWastePos < 0 or yWastePos > 700: #remove ewaste if off screen
    drawScene()

def drawEvilBat():
    global x_evilbat_pos, y_evilbat_pos
    screen.blit(pygame.transform.scale(evilbatImage, (100, 100)), (x_evilbat_pos, y_evilbat_pos))
    y_evilbat_pos += 15 #Speed of e-waste yPos
    if y_evilbat_pos > height: #Makes evil battery generate randomly from the top going vertically down
        x_evilbat_pos = random.randint(0, 1000)
        y_evilbat_pos = 0
    return    

def drawStars():
    pygame.draw.circle(screen, YELLOW, (200,100), 10, 10)



#-----------MOVING OBJECTS AND RESETTING POSITIONS-----------
def move_ship(): #Moving ship
    global x_ship_pos, x_ship_speed, y_ship_pos, y_ship_speed
    x_ship_pos += x_ship_speed
    if x_ship_pos < -25: #Making sure spaceship doesn't go off screen
        x_ship_pos = -25
    elif x_ship_pos > 925:
        x_ship_pos = 925

    y_ship_pos += y_ship_speed
    if y_ship_pos < 0: #Making sure spaceship doesn't go off screen
        y_ship_pos = 0
    elif y_ship_pos > 600:
        y_ship_pos = 600

def resetShip(): #Resets Gamepage
    global x_ship_pos, y_ship_pos, K_DOWN, K_LEFT, K_RIGHT, K_UP
    x_ship_pos = 500 # ship x coord
    y_ship_pos = 600 # ship y coord
    shipEats = 0
    KEY_DOWN = False
    KEY_LEFT = False
    KEY_RIGHT = False
    KEY_UP = False
    direction = 180


def move_battery(): #Moving battery
    global x_battery_pos, y_battery_pos, battery_direction, is_battery_on_screen  #GLOBAL VARIABLES
    if is_battery_on_screen:
        if battery_direction == "UP":
            y_battery_pos -= 70 #How fast the battery moves
        elif battery_direction == "DOWN":
            y_battery_pos += 70
        elif battery_direction == "RIGHT":
            x_battery_pos += 70
        elif battery_direction == "LEFT":
            x_battery_pos -= 70

        if x_battery_pos < 0 or x_battery_pos > 1000 or y_battery_pos < 0 or y_battery_pos > 700: #remove battery if off screen
            is_battery_on_screen = False


#--------Defning fonts and buttons--------

#Fonts
font = pygame.font.SysFont("Courier", 100) #Font for titles
font2 = pygame.font.SysFont("Courier", 30) #Small Font 
font3 = pygame.font.SysFont("Courier", 60) #Font for small titles

#Defining Buttons
playBtn = pygame.Rect(280, 410, 450,120) #Play Game Button
instrBtn = pygame.Rect(350, 550, 300,120) #Instructions Button
quitBtn = pygame.Rect(680, 550, 300,120) #Quit Button
leaderBtn = pygame.Rect(30, 550, 300,120) #Leaderboard Button
mainMenuBtn = pygame.Rect(870, 20, 120,30) #mainMenuBtn

running = True
myClock = pygame.time.Clock()
mx = my = 0

display_main_screen() #Calling main screen function

#GAME LOOP
while running:
    button = 0
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False  
        elif event.type == pygame.MOUSEBUTTONDOWN:
            mouse_pos = event.pos #Gets mouse position
            if in_game == False:
                if playBtn.collidepoint(mouse_pos):
                    gamePage()
                    in_game = True              
                elif quitBtn.collidepoint(mouse_pos):
                    running = False
                elif instrBtn.collidepoint(mouse_pos):
                    instrPage()
                elif leaderBtn.collidepoint(mouse_pos):
                    leaderPage()
                elif mainMenuBtn.collidepoint(mouse_pos):
                    display_main_screen()

        #ALLOWS SPACESHIP TO MOVE AND CHECKS WHICH DIRECTION SHIP GOES SO IT SAVES DIRECTION AND BATTERY SHOOTS THAT WAY
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_UP:
                direction = 0
                y_ship_speed = -20 #Spaceship speed
                if is_battery_on_screen == False:
                    battery_direction = "UP" #Saves direction as up
            if event.key == pygame.K_DOWN:
                y_ship_speed = 20 #Spaceship speed
                direction = 180
                if is_battery_on_screen == False:
                    battery_direction = "DOWN" #Saves direction as down
            if event.key == pygame.K_LEFT:
                x_ship_speed = -20 #Spaceship speed
                direction = 90
                if is_battery_on_screen == False:
                    battery_direction = "LEFT" #Saves direction as left
            if event.key == pygame.K_RIGHT:
                x_ship_speed = 20 #Spaceship speed
                direction = 270
                if is_battery_on_screen == False:
                    battery_direction = "RIGHT" #Saves direction as right

            if event.key == pygame.K_SPACE:
                if is_battery_on_screen == False: #Shoots battery
                    is_battery_on_screen = True
                    x_battery_pos = x_ship_pos
                    y_battery_pos = y_ship_pos

            if event.key == pygame.K_ESCAPE:
                in_game = False
                display_main_screen() #Goes back to main menu 

        elif event.type == pygame.KEYUP:
            if event.key == pygame.K_UP:
                y_ship_speed = 0
            elif event.key == pygame.K_DOWN:
                y_ship_speed = 0
            elif event.key == pygame.K_LEFT:
                x_ship_speed = 0
            elif event.key == pygame.K_RIGHT:
                x_ship_speed = 0    

    if in_game:
        #Calling action functions
        move_ship()
        move_battery()

        #Clearing the screen
        drawScene(screen, mx, my, button)

        #drawing objects to the screen
        draw_ship()
        draw_explosivebattery()
        drawEwaste()
        drawStars()

    pygame.display.flip()

    #waits long enough to have 100 fps
    myClock.tick(100)


#Quit Pygame
pygame.quit()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • uses `pygame.Rect()` to keep position and size for every element - it has `rect.center` which you can use to get or set position. For example to center player on screen - `player.rect.center = screen.get_rect().center`. Similar way you can center text on button or other two objects. – furas Jan 18 '20 at 01:24
  • you rotate battery to `newImage` but you always blit old image `batteryImage` – furas Jan 18 '20 at 01:53
  • Please reduce your code to a [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) to make it more minimal and readeble – Wouterr Jan 18 '20 at 14:49

1 Answers1

1

When you draw the ship, then you have to rotate it around its center: (See How do I rotate an image around its center using Pygame?)

def draw_ship(): 
    global shipImage, direction
    imageRect = shipImage.get_rect(topleft = (x_ship_pos, y_ship_pos))
    newImage = pygame.transform.rotate(shipImage, direction)
    newImageRect = newImage.get_rect(center = imageRect.center)
    screen.blit(pygame.transform.scale(newImage, (100, 100)), newImageRect.topleft)

It is not necessary to do that for the battery, because we will compute the proper position for the top left of the battery when SPACE is pressed.

def draw_explosivebattery(): 
    if is_battery_on_screen: 
        newImage = pygame.transform.rotate(batteryImage, direction)
        screen.blit(pygame.transform.scale(batteryImage, (30, 40)), (x_battery_pos, y_battery_pos))

For all the computations you should use pygame.Rect:

while running:
    button = 0
    for event in pygame.event.get():
            # [...]

        elif event.type == pygame.KEYDOWN:
            # [...]

            if event.key == pygame.K_SPACE:
                if is_battery_on_screen == False: #Shoots battery
                    is_battery_on_screen = True

                    tempRect = shipImage.get_rect(topleft = (x_ship_pos, y_ship_pos))
                    newImage = pygame.transform.rotate(shipImage, direction)
                    ship_rect = newImage.get_rect(center = tempRect.center)
                    rotBatteryImage = pygame.transform.rotate(batteryImage, direction)
                    battery_rect = rotBatteryImage.get_rect()
                    if battery_direction == "UP":
                        battery_rect.midbottom = ship_rect.midtop
                    elif battery_direction == "DOWN":
                        battery_rect.midtop = ship_rect.midbottom
                    elif battery_direction == "RIGHT":
                        battery_rect.midleft = ship_rect.midright
                    elif battery_direction == "LEFT":
                        battery_rect.midright = ship_rect.midleft
                    x_battery_pos, y_battery_pos = battery_rect.topleft

Explanation:

Compute the bounding rectangle of the rotated ship (ship_rect):

tempRect = shipImage.get_rect(topleft = (x_ship_pos, y_ship_pos))
newImage = pygame.transform.rotate(shipImage, direction)
ship_rect = newImage.get_rect(center = tempRect.center)

Get the size of the rotated battery (battery_rect):

rotBatteryImage = pygame.transform.rotate(batteryImage, direction)
battery_rect = rotBatteryImage.get_rect()

Set the location of the bounding rectangle of the battery, dependent on the direction. e.g. if it is shoot to the left battery_rect.midright = ship_rect.midleft:

if battery_direction == "UP":
    battery_rect.midbottom = ship_rect.midtop
elif battery_direction == "DOWN":
    battery_rect.midtop = ship_rect.midbottom
elif battery_direction == "RIGHT":
    battery_rect.midleft = ship_rect.midright
elif battery_direction == "LEFT":
    battery_rect.midright = ship_rect.midleft

Assign the top left position of the bounding rectangle to x_battery_pos, y_battery_pos:

x_battery_pos, y_battery_pos = battery_rect.topleft
Rabbid76
  • 202,892
  • 27
  • 131
  • 174