0

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()
Andy
  • 263
  • 1
  • 11

1 Answers1

1

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

jmetz
  • 12,144
  • 3
  • 30
  • 41
  • ??? The cannon's startpoint is the center of the player (with a slight offset allowed for the witdth of the line) I do also use the cannon's x and y as endpoints.. More info? – Andy Apr 29 '14 at 10:06
  • @Andy: As I pointed out the end point contains the cannons self.x and y... which travel at a different speed to the player... causing a lengthening line. – jmetz Apr 29 '14 at 10:10
  • The line lengthens when the player is stationary, plus, the cannon x and y are relative the players position – Andy Apr 29 '14 at 10:12
  • @Andy: That's because the speed of the cannon is independent of the speed of the player. – jmetz Apr 29 '14 at 10:13
  • @Andy: cannon x and y are **not** relative to the players position. They change independently - the Cannon update function increments them by xSpeed and ySpeed. – jmetz Apr 29 '14 at 10:15
  • Okay, I think I get where you are going but after playing around with it a bit I can promise two things. 1. The player moving does not affect it and 2. The fact that the cannon.xSpeed changes is also irrelevant. by using (player.x + 14) + self.x I am offsetting the endpoint of the cannon relative to the player's center (the player's width is 30) I leave an offset for the width of the line – Andy Apr 29 '14 at 10:20
  • Just got your newer comment. They are relative. They change, yes but I probably should have phrased this better, when the line is actually drawn they are relative the player.x and player.y – Andy Apr 29 '14 at 10:21
  • @Andy: At what point are they made relative?? I see no statements that assign into cannon's x and y, which depends on the players position... – jmetz Apr 29 '14 at 10:23
  • pygame.draw.line(screen, red, player.center, ((player.x + 14) + self.x, (player.y + 14) + self.y), 2) In this drawing line they are made relative for the endpoints (Endpoint x = (player.x + 14 ((To get the center x of player)) ) + self.x) self.x to get the offset from the center x of the player. – Andy Apr 29 '14 at 10:25
  • @Andy: This line does **not** connect self.x with player.x etc. It only sets that as the end point of the line. self.x and player.x remain totally independent. – jmetz Apr 29 '14 at 10:30
  • True, but with them both leaning on each other for the end drawing how does that independance effect the size of the line? – Andy Apr 29 '14 at 10:32
  • Because they both change totally independently... if I set the end point of my gun to be a combination of my position and the position of a plane travelling from london to nyc, then even though they both appear in the expression for the end point of my line they are not linked, and the length of the line will change as the plane moves... – jmetz Apr 29 '14 at 10:36
  • True, but I have already pointed out that the movement of the player has no effect on the cannon's length. Simply keeping the player stationary and moving the cannon in circles will extend it – Andy Apr 29 '14 at 10:37
  • @Andy: indulge me: try setting the end point relative only to the player center and some offset... – jmetz Apr 29 '14 at 10:41
  • Sorry for the delay, went to get a bite to eat. I tried it but the problem with this is that the line is unable to rotate. It just more or less sits there. BTW Thanks for all the help. – Andy Apr 29 '14 at 11:03
  • @Andy: no problem: the issue however is still basically though that Cannon's x and y are changing differently to desired; if you want circular rotation they should change according to something like `r * sin(2*PI*t/PERIOD)` and `r * cos(2*PI*t/PERIOD)` – jmetz Apr 29 '14 at 11:09
  • Dang, is it possible that your propose some kind of counter code. I think that's triggernometry and I haven't actually done that yet so don't quite understand how you would go about using it – Andy Apr 29 '14 at 11:12
  • @Andy: I don't think you're going to manage circular motion without trigonometry... – jmetz Apr 29 '14 at 11:19
  • Bugger, any other ideas? – Andy Apr 29 '14 at 11:19