Question

Alright, so I am making a game where a character moves around the screen and shoots enemies. He hes a cannon on top of him ( a line ;) ) but this is where I am having the problem. In the class cannon (below) I rotate the line around the player and this works fine. The problem I am having is that the line somehow grows in length :/ Not positive why, any help is appreciated. It rotates if you let it go round and round to many times (Sounds a bit childish but yeah)

P.S (Sorry for the long code, thought I would include it anyway. All that you should really need is under the cannon class. Thanks)

import pygame, sys
from pygame.locals import *

# Classes

class Bullet(pygame.sprite.Sprite):

    def __init__(self, x, y, targetX, targetY):
        self.x = x
        self.y = y
        self.targetX = targetX
        self.targetY = targetY
        pygame.sprite.Sprite.__init__(self, bulletGroup) 

    def update(self):
        pygame.draw.rect(screen, (251, 231, 9), (self.x, self.y, 5, 5))

class Cannon(pygame.sprite.Sprite):

    def __init__(self):
        self.x = 0
        self.y = -30
        self.xSpeed = 10
        self.ySpeed = 10
        self.right = False
        self.left = False

    def update(self):
        if self.y >= 0:
            self.xSpeed =  self.xSpeed * -1
        print self.x
        if self.right:
            if self.x < 0:
                self.x += self.xSpeed
                self.y -= self.ySpeed
            else:
                self.x += self.xSpeed
                self.y += self.ySpeed

        if self.left:
            if self.x > 0:
                self.x -= self.xSpeed
                self.y -= self.ySpeed
            else:
                self.x -= self.xSpeed
                self.y += self.ySpeed

        self.xSpeed = 0.5
        self.ySpeed = 0.5

        pygame.draw.line(screen, red, player.center, ((player.x + 14) + self.x, (player.y + 14) + self.y), 2)





class Player(pygame.sprite.Sprite):

    def __init__(self, config):
        self.loadConfig(config)
        self.x = 250
        self.y = 250
        self.up = False
        self.down = False
        self.right = False
        self.left = False
        self.canShoot = True
        self.canShootTicks = 0
        self.shooting = False

    def loadConfig(self, config):
        loaded = 0
        for line in config:

            if "health - " in line:
                self.health = int(line[9:])
                loaded += 1

            elif "damage - " in line:
                self.damage = int(line[9:])
                loaded += 1

        if loaded < 2:
            loaded = 0
            config = open("config.txt", "w")
            config = open("config.txt", "r+")
            self.writeToConfig(config)

    def writeToConfig(self, config):
        config.write("health - 100\n")
        config.write("damage - 10\n")
        config.seek(0)
        self.loadConfig(config)

    def update(self):
        if self.canShootTicks > 2:
            self.canShoot = True
        self.shoot()
        if self.up and self.y > 20:
            self.y -= 5
        if self.right and self.x < 550:
            self.x += 5
        if self.left and self.x > 20:
            self.x -= 5
        if self.down and self.y < 550:
            self.y += 5
        self.canShootTicks += 1
        self.center = (self.x + 14, self.y + 15)
        screen.blit(playerImg, (self.x, self.y))

    def shoot(self):
        if player.canShoot:
            if player.shooting:
                bullet = Bullet(self.x, self.y, 10, 10)
                bulletGroup.add(bullet)
                self.canShootTicks = 0
                self.canShoot = False



# Functions


def getResources():

    wallImgTop = pygame.image.load("wallTop.png")
    wallImgSide = pygame.image.load("wallSide.png")
    wallImgCorner1 = pygame.image.load("wallCorner1.png")
    wallImgCorner2 = pygame.image.load("wallCorner2.png")
    wallImgCorner3 = pygame.image.load("wallCorner3.png")
    wallImgCorner4 = pygame.image.load("wallCorner4.png")
    playerImg = pygame.image.load("player.png")

    return (wallImgTop, wallImgSide, wallImgCorner1, wallImgCorner2, wallImgCorner3, wallImgCorner4, playerImg)


def drawWalls():
    for i in range (4):
        if i == 0 or i == 2:
            direction = 0
        else:
            direction = 580

        for n in range(20):
            if i < 2:
                screen.blit(wallImgTop, (n * 30, direction))
            else:
                screen.blit(wallImgSide, (direction, n * 30))

    screen.blit(wallImgCorner1, (-6, -1))
    screen.blit(wallImgCorner2, (567, -6))
    screen.blit(wallImgCorner3, (-1, 564))
    screen.blit(wallImgCorner4, (564, 567))


def loadSave():

    try:
        config = open("config.txt", "r+")
    except IOError:
        config = open("config.txt", "w")
        config = open("config.txt", "r+")

    player = Player(config)

    return player

# Starting out

pygame.init()

screen = pygame.display.set_mode((600, 600), 0, 32)
pygame.display.set_caption("Upgrady Shooter")
clock = pygame.time.Clock()

# Variables

FPS = 50

red = (255, 0, 0)
black = (0, 0, 0)




# Get goin'

wallImgTop, wallImgSide, wallImgCorner1, wallImgCorner2, wallImgCorner3, wallImgCorner4, playerImg = getResources()

bulletGroup = pygame.sprite.Group()
player = loadSave()
cannon = Cannon()


while True:

    screen.fill(black)
    drawWalls()

    bulletGroup.update()
    player.update()
    cannon.update()

    for event in pygame.event.get():

        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

        elif event.type == pygame.KEYDOWN:

            if event.key == K_w:
                player.up = True

            elif event.key == K_d:
                player.right = True

            elif event.key == K_a:
                player.left = True

            elif event.key == K_s:
                player.down = True

            elif event.key == K_SPACE:
                player.shooting = True

            elif event.key == K_LEFT:
                cannon.left = True


            elif event.key == K_RIGHT:
                cannon.right = True

        elif event.type == pygame.KEYUP:

            if event.key == K_w:
                player.up = False

            elif event.key == K_d:
                player.right = False

            elif event.key == K_a:
                player.left = False

            elif event.key == K_s:
                player.down = False

            elif event.key == K_SPACE:
                player.shooting = False

            elif event.key == K_LEFT:
                cannon.left = False

            elif event.key == K_RIGHT:
                cannon.right = False

    pygame.display.update()
Was it helpful?

Solution

Independent positions

The speed of the Player and the speed of the Cannon are not the same, the first is essentially 5 (e.g. self.x += 5) and the second is 10 to start (self.xSpeed = 10) but then set to 0.5 (self.xSpeed = 0.5).

Then as you use the player's centre as the start point for the line, and include the cannon's x and y as the end point, the line changes length.

More explicitly, your cannon drawing line is

pygame.draw.line(screen, red, player.center, ((player.x + 14) + self.x, (player.y + 14) + self.y), 2)

such that the start point of the line is player.center, while the end point contains self.x and self.y...

Circular motion

In order to implement circular motion you need to use something like

x = r * sin(2*PI*t/PERIOD),  
y = r * cos(2*PI*t/PERIOD)

or more likely these would be put into a lookup table (i.e. generate all values of x and y for 0 to 2 PI).

Other equations can also be used

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top