1

i am still learning on how to use pygame and i just created a space invader inspired game. but one issue that i have right now is that the bullet does not come out accordingly to my object's location. instead it only comes out from the bottom of the screen. i want my bullet to come out accordingly to my object no matter if its moving up, down, right or left. thank you in advance!!

import pygame
import random
import math
#intialize the pygame
pygame.init()

#create the screen
screen = pygame.display.set_mode((700,583))



#Caption and icon
pygame.display.set_caption("Yoshi & Fruits")
icon = pygame.image.load("Yoshi_icon.png")
pygame.display.set_icon(icon)

#Player
playerImg = pygame.image.load("YoshiMario.png")
playerX = 370
playerY = 480
playerX_change = 0
playerY_change = 0

#Enemy
enemyImg = pygame.image.load('msh1.png')
enemyX = random.randint(0,735)
enemyY = random.randint(50,150)
enemyX_change = 2
enemyY_change = 30


#Knife

# ready - you cant see the knife on the screen
# fire - the knife is currently moving

knifeImg = pygame.image.load('diamondsword3.png')
knifeX = 0
knifeY = 480
knifeX_change = 0
knifeY_change = 10
knife_state = "ready"

score = 0

def player(x,y):
    screen.blit(playerImg, (x, y))

def enemy(x,y):
    screen.blit(enemyImg, (x, y))

def fire_knife(x,y):
    global knife_state
    knife_state = "fire"
    screen.blit(knifeImg,(x + 16, y + 10))

def isCollision(enemyX,enemyY,knifeX,knifeY):
    distance = math.sqrt((math.pow(enemyX - knifeX,2)) + (math.pow(enemyY - knifeY,2)))
    if distance < 27:
        return True
    else:
        return False
    
#game loop
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    #if keystroke is pressed check whether its right or left
    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_LEFT:
            playerX_change = -2
        if event.key == pygame.K_RIGHT:
           playerX_change = 2
        if event.key == pygame.K_UP:
           playerY_change = -2
        if event.key == pygame.K_DOWN:
           playerY_change = 2
        if event.key == pygame.K_SPACE:
            if knife_state is "ready":
                # get the current x coordinate of yoshi
                knifeX = playerX
                fire_knife(playerX,knifeY)
    
    if event.type == pygame.KEYUP:
        if event.key == pygame.K_LEFT:
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                playerX_change = 0
            if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
                playerY_change = 0
            
    # RGB - Red, Green, Blue
    screen.fill((0, 255, 0))
    
    #add a wallpaper
    bgimage=pygame.image.load("Background.png")
    screen.blit(bgimage, (0, 0))
    

    # 5 = 5 + -0.1 ->5 = 5 - 0.1
    # 5 = 5 + 0.1

    # checking for boundaries of yoshi/mushroom so it doesnt go out of bounds
    playerX += playerX_change
    if playerX < 0:
        playerX = 0
    elif playerX > 645:
        playerX = 645

    playerY += playerY_change    
    if playerY < 0:
        playerY = 0
    elif playerY > 500:
        playerY = 500

    # enemy movement
    enemyX += enemyX_change
    if enemyX <= 0:
        enemyX_change = 2
        enemyY += enemyY_change
    elif enemyX > 645:
        enemyX_change = -2
        enemyY += enemyY_change

    # knife movement
    if knifeY <= 0:
        knifeY = 480
        knife_state = "ready"
        
    if knife_state is "fire":
        fire_knife(knifeX,knifeY)
        knifeY -= knifeY_change
        
    # collision
    collision = isCollision(enemyX,enemyY,knifeX,knifeY)
    if collision:
        knifeY = 480
        knife_state = "ready"
        score += 1
        print(score)
        enemyX = random.randint(0,735)
        enemyY = random.randint(50,150)
        
    player(playerX,playerY)
    enemy(enemyX,enemyY)
    pygame.display.update()
harraz syah
  • 45
  • 1
  • 7
  • Set the position to the same as the playerX and playerY coordinate (maybe subtract or add a little bit so it’s in the middle or wherever you want the bullet). However you need a specific variable like bulletx and set it to playerX if the nullet isn’t shot. –  Dec 08 '20 at 21:20

1 Answers1

1

I assume by "bullet" you are referring to "knife" in the code.

The code is not tracking the change in the knife's co-ordinates. Sure it's created at the player's X co-ordinate, but nothing remembers this change. So let's modify fire_knife() to simply remember the changes in the state of the knife, including the new X & Y.

def fire_knife( x, y ):
    """ Start a knife flying upwards from the player """
    global knife_state, knifeX, knifeY
    knifeX = x + 16
    knifeY = y + 10
    knife_state = "fire"

And create a collision handler that automatically resets the knife back to "ready":

def knife_hits( enemyX, enemyY ):
    """ Return True if the knife hits the enemy at the given (x,y).
        If so, prepare the knife for firing again. """
    global knife_state, knifeX, knifeY
    collision_result = False
    if ( knife_state == "fire" and isCollision( enemyX, enemyY, knifeX, knifeY ) ):
        knife_state = "ready"
        collision_result = True
    return collision_result

Then create another function to separately draw the knife, if it's in the correct state.

def draw_knife( screen ):
    """ If the knife is flying, draw it to the screen """
    global knife_state, knifeImg, knifeX, knifeY
    if ( knife_state == "fire" ):
        screen.blit( knifeImg, ( knifeX, knifeY ) )

And, for the sake of completeness, a function to update the knife's position, and reset the knife_state when it goes off-screen.

def update_knife():
    """ Make any knife fly up the screen, resetting at the top """
    global knife_state, knifeX, knifeY, knifeY_change
    # if the knife is already flying, move it
    if ( knife_state == "fire" ):
        knifeY -= knifeY_change
        if ( knifeY <= 0 ):
            knife_state = "ready"   # went off-screen

So that gives a new main loop calling these functions:

#game loop
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    #if keystroke is pressed check whether its right or left
    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_LEFT:
            playerX_change = -2
        if event.key == pygame.K_RIGHT:
           playerX_change = 2
        if event.key == pygame.K_UP:
           playerY_change = -2
        if event.key == pygame.K_DOWN:
           playerY_change = 2
        if event.key == pygame.K_SPACE:
            if knife_state is "ready":
                # Fire the knife at the coordinates of yoshi
                fire_knife( playerX, playerY )   # create a new flying knife

    # ...

    # enemy movement
    enemyX += enemyX_change
    if enemyX <= 0:
        enemyX_change = 2
        enemyY += enemyY_change
    elif enemyX > 645:
        enemyX_change = -2
        enemyY += enemyY_change

    update_knife()                         # move the flying knife (if any)

    if ( knife_hits( enemyX, enemyY ) ):   # is there a knife-enemy-collision?
        score += 1
        print(score)
        enemyX = random.randint(0,735)
        enemyY = random.randint(50,150)
    else:
        draw_knife( screen )               # paint the flying knife (if any)
        
    player(playerX,playerY)
    enemy(enemyX,enemyY)
    pygame.display.update()

Putting all the modifications to the knife position into functions makes your main loop simpler, and keeps most knife-code contained into a single group of functions. It would probably be better again to make a Knife class with these functions, but this is a simple start.

Kingsley
  • 14,398
  • 5
  • 31
  • 53
  • thank you for replying. i already try the code that you gave and thankfully, the bullet/knife now comes out from the object. but apparently another problem appear. apparently the knife now moves north east when the object shoot it. before this, i want the knife to be shooted upward, as in north because the enemy appear from the top of the screen and only moves left to right. is there a way to fix this? – harraz syah Dec 09 '20 at 10:06
  • @harrazsyah - Check your code for where `knifeX` is being changed. That can be the only way it's moved, since the knife is *always* (and only) drawn at `(knifeX, knifeY)`. Are you sure the `move_knife()` function *only* changes `knifeY` ? – Kingsley Dec 09 '20 at 21:37
  • 1
    i already change it. apparently i just need to change from `fire_knife(knifeX,knifeY)` to `fire_knife(playerX,knifeY)` and it already solved my problem. thank you – harraz syah Dec 10 '20 at 06:45