Jump to content

  • Log In with Google      Sign In   
  • Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

Making an image shoot


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
35 replies to this topic

#1 colts18   Members   -  Reputation: 100

Like
1Likes
Like

Posted 05 February 2011 - 02:14 PM

Hey guys I have a tank and I want it to shoot a bullet I created. I want the bullet to continue flying through the air until it hits the enemy tank and the tank explodes. I have an image for that too. Does anyone know how?

Sponsor:

#2 colts18   Members   -  Reputation: 100

Like
0Likes
Like

Posted 05 February 2011 - 02:22 PM

Here is the code:

import pygame

class Tank:

    def __init__(self):
        self.tank = pygame.image.load("tank.png")
        self.x = -200
        self.y = 20
    def draw(self, surface):
        surface.blit(self.tank, (self.x, self.y))

class Lvl_1:
    
    def __init__(self):
        self.floor = pygame.image.load("floor.png")
    def draw(self, surface):
        surface.blit(self.floor, (0, 0))

class Enemy_tank:

    def __init__(self):
        self.enemy_tank = pygame.image.load("enemy_tank.png")
    def draw(self, surface):
        surface.blit(self.enemy_tank, (100, -40))

pygame.init()                                                   
background_color = (0,0,0)                                      
(width, height) = (640, 480)                                    
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Game Window')                       
clock = pygame.time.Clock()                                     
tank = Tank()
lvl_1 = Lvl_1()
enemy_tank = Enemy_tank()
pygame.key.set_repeat(1,50)                                     
running = True                   
    
while running:

    screen.fill (background_color)                          
    tank.draw(screen)
    lvl_1.draw(screen)
    enemy_tank.draw(screen)
    pygame.display.flip()                                   
    clock.tick(30)                                          

    for event in pygame.event.get():                        


            if event.type == pygame.QUIT:                   
                        running = False
            elif event.type == pygame.KEYDOWN:              
                    if event.key == pygame.K_RIGHT:
                            tank.x += 5                     
                    if event.key == pygame.K_LEFT:
                            tank.x -= 5


#3 mrwonko   Members   -  Reputation: 122

Like
0Likes
Like

Posted 05 February 2011 - 03:09 PM

You could create a new class "Bullet" which represents bullets. It needs some kind of Update() function which moves the bullet forward based on the time since the last frame (new position = old position + time * velocity). You could also check for collisions there (e.g. Bullet hits Enemy_tank).

Does pygame keep track of resource management? If you call pygame.image.load twice for the same image, will it be loaded again (bad) or will you get the same image (good)? If the former is the case, you'll need to avoid duplicate loading yourself, you don't want a new image to be created for each Bullet object.

And your Tank needs a Shoot() function which creates a new Bullet, which is then added to some kind of list so you can keep track of it (e.g. call Update()).


This is a pretty general answer since your question is rather vague, too. Should give you a general idea of how you can do it. (There are many ways of doing it.) If you need more specific information, ask more specific questions. :rolleyes:

So long,
Mr. Wonko

#4 Enders   Members   -  Reputation: 125

Like
0Likes
Like

Posted 05 February 2011 - 03:26 PM

Back again eh?

Here is a nice link to some python game programming examples.

I used these when I was first learning.

http://eli.thegreenplace.net/2008/12/13/writing-a-game-in-python-with-pygame-part-i/

The biggest thing you should figure out is to learn to think "how do I do something"

I learned a while ago, that when i wanted something to happen in a game, I would write down everything that I wanted to happen. For example:

* I want a bullet to shoot from my tank

* It will shoot to the right
* It's speed will be 10 pixels per frame
* Gravity will not effect it
* When it hits something, the bullet will go away.
* If it does not hit something, and goes off screen, the bullet will go away.
* There can only be 1 bullet on screen at a time.

This is a nice simple list of the characteristics of a bullet. It will give me rules to follow. Now I will have to try and it and create code for the bullet. The bullet is a bit more dynamic the the tank as it requires more rules in game. But we can start with a class to give it it's image and x, y location. Probably something where the bullet.y is equal to tank.y and its x is offsetted some.

You will probably need to give the bullet a boolean for being on screen.

And maybe another boolean for on hit.

Now in your main loop, if space bar is press, you can have it activate a function in the bullet class to activate the on screen flag, and change its x and y position to be near your tank.

You will want to make it so that it will only do that if the on screen flag is set to false.

Also in the main loop, right behind the draw function for the bullet, you can have an update position function, That will increase it's x position 10 to the right.

After that call, you can have another function to check its position compared to the end of the screen and see if it will collide with another tank. If the check is true, then you can change the on hit flag to true. So now when the draw function is called, the on hit flag will show an explosion picture instead of a bullet picture. After the picture is shown, you change the on hit and on screen flag to false.

It is pretty rudimentary. But take a look at that link i provided. It is pretty nice.

Good luck! :)

#5 colts18   Members   -  Reputation: 100

Like
0Likes
Like

Posted 05 February 2011 - 07:33 PM

Ok I started to create the bullet class but I'm still not sure how to add the spacebar input in the main loop.

#6 colts18   Members   -  Reputation: 100

Like
0Likes
Like

Posted 05 February 2011 - 08:37 PM

This is the partially completed bullet class is there some special way to draw the bullet since I don't want to draw it until the space bar is pressed?

class Bullet:

    def __init__(self):
        self.bullet = pygame.image.load("tank_bullet.png")
        self.speed = 10


#7 Fl4sh   Banned   -  Reputation: 34

Like
0Likes
Like

Posted 05 February 2011 - 11:54 PM

This is the partially completed bullet class is there some special way to draw the bullet since I don't want to draw it until the space bar is pressed?

class Bullet:

    def __init__(self):
        self.bullet = pygame.image.load("tank_bullet.png")
        self.speed = 10



Something like:

1. Wait for the spacebar keydown event
a.Get position of the person or ship
b. From that point, have it travel as you want
c. use a bool to determine if it has hit something.
They hated on Jeezus, so you think I give a f***?!

#8 colts18   Members   -  Reputation: 100

Like
0Likes
Like

Posted 06 February 2011 - 11:37 AM

I'm having trouble getting it to shoot I'm not completely sure if I'm doing it right can someone tell me if I am and if not what am I doing wrong? This is what I have so far.

class Bullet:

    def __init__(self):
        self.bullet = pygame.image.load("tank_bullet.png")
        self.speed = 10
        self.y = tank.y
        self.x = tank.x
    def draw(self, surface):
        if event.key == pygame.K_SPACE:
            surface.blit(self.bullet, (self.x, self.y))


#9 Burnt_Fyr   Members   -  Reputation: 560

Like
0Likes
Like

Posted 06 February 2011 - 12:37 PM

I'm having trouble getting it to shoot I'm not completely sure if I'm doing it right can someone tell me if I am and if not what am I doing wrong? This is what I have so far.

class Bullet:

    def __init__(self):
        self.bullet = pygame.image.load("tank_bullet.png")
        self.speed = 10
        self.y = tank.y
        self.x = tank.x
    def draw(self, surface):
        if event.key == pygame.K_SPACE:
            surface.blit(self.bullet, (self.x, self.y))


I've been following this thread, and your previous. To be honest, I don't think you have what it takes at this point in time, to accomplish what you are trying to do. You need to understand what is going on with your code, and not just blindly copy peoples suggestions here. You will not get anywhere, and eventually those who are helping will grow tired of your neediness. I'm sorry it just needs to be said. With that out of the way, let's look at POSSIBLE solutions.

You were given a *great* leg up by Enders, who went though the process of design, rather than just providing an answer. You ran with it and got stuck. These things happen, don't let it get you down. Fl4sh provided a general solution, and you tried again, resulting in your current code. Looking at that, your saying that if your drawing, and the space key is pressed, then blit the surface. Does this sound like what you want to have happen? Should the bullet itself be firing itself?

Let's move back a sec and look at the tank class, it has a method to draw itself, but that is it. doesn't a tank do more? lets add 2 methods to tank. Fire, and update. Fire is where we will handle the creating of a bullet, and update will be a method that will allow us to handle updates to the tank. Once again i've no experience with python, so I have no idea if this syntax is correct, but hopefully you will understand enough to make it work

def update(time) :
	// the time variable allows us to watch time elapsed for things like reloading ammo, special moves, etc, but if youd don't need it it's fine to leave it out for now
if event.Key == pygame.K_SPACE:
self.fire()
sorry for the c style comments, hope you can see what's going on there. No code, just a design template for you to work with. so the tank will now fire if the space key is down during it's update.

def fire():
// create a bullet
//set the bullets position to the tanks position
// give the bullet a direction
// add the bullet to a list of bullets
So the fire method will create, and initialize the bullet object so it is ready to go

def update(time) :
self.x += self.xdirection *self.speed * time
self.y += self.ydirection * self.speed * time
This update method will fit in the bullet class. basically every update, it moves a distance along it's direction, which is it's speed * time elapsed.

Now we have a method for creating a bullet, a method for updating it, and a method to update the tank. your main loops will now look something like

while running

//update game state
tank.update(time) 	// you will need to get how much time has elapsed since last frame
enemy_tank.update(time)
foreach(bullet in bulletlist) 
{
    bullet.update()
}        	

// gamestate is updated, so lets draw it

    tank.draw(screen)
    lvl_1.draw(screen)
    enemy_tank.draw(screen)
    pygame.display.flip()                       			
    clock.tick(30)


#10 colts18   Members   -  Reputation: 100

Like
0Likes
Like

Posted 06 February 2011 - 05:32 PM

This is what I tried for the tank and bullet classes but it still won't shoot:

class Tank:

    def __init__(self):
        self.tank = pygame.image.load("tank.png")
        self.x = -200
        self.y = 20
    def draw(self, surface):
        surface.blit(self.tank, (self.x, self.y))
    def update(time):
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                self.fire()
                
class Bullet:
    
    def fire():
        self.bullet = pygame.image.load("tank_bullet.png")
        self.y = tank.y
        self.x = tank.x
        self.speed = 10
        right = self.x + 5
    def update(time): 
        self.x += self.x, right * self.speed * 30
        self.y += self.y, right * self.speed * 30


#11 Fl4sh   Banned   -  Reputation: 34

Like
0Likes
Like

Posted 06 February 2011 - 09:06 PM

Doesn't pygame have bounding rectangles and stuff? ;o
They hated on Jeezus, so you think I give a f***?!

#12 Burnt_Fyr   Members   -  Reputation: 560

Like
0Likes
Like

Posted 07 February 2011 - 07:46 AM

The tank FIRES the bullet... the bullet doesn't fire itself...

#13 colts18   Members   -  Reputation: 100

Like
0Likes
Like

Posted 07 February 2011 - 02:16 PM

Ok I moved the fire() to the tank but still not shooting

class Tank:

    def __init__(self):
        self.tank = pygame.image.load("tank.png")
        self.x = -200
        self.y = 20
    def draw(self, surface):
        surface.blit(self.tank, (self.x, self.y))
    def update(time):
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                self.fire()
    def fire():
        self.bullet = pygame.image.load("tank_bullet.png")
        self.y = tank.y
        self.x = tank.x
        self.speed = 10
        right = self.x + 5
    def update(time): 
        self.x += self.x, right * self.speed * 30
        self.y += self.y, right * self.speed * 30


#14 Fl4sh   Banned   -  Reputation: 34

Like
0Likes
Like

Posted 07 February 2011 - 02:34 PM

Colts like someone else said, you can't just mindlessly copy/paste peoples suggestions and expect it to work. Posted Image

You have to understand what's going on with the code... at-least to some degree. Posted Image
They hated on Jeezus, so you think I give a f***?!

#15 DarklyDreaming   Members   -  Reputation: 330

Like
0Likes
Like

Posted 07 February 2011 - 02:34 PM

I think you are confused. Fire() should create an instance of Bullet which in turn needs to be updated (by calling <myFancyBulletName>.Update()). Load the image in the __init__() method of Bullet. After all, you DON'T want that image loaded everytime someone presses fire, now do you? You want every Bullet instance to have that image, which logically should then be loaded upon everytime a Bullet is created (actually, preferably you would load the image once somewhere else but let's not get deeper into that right now..)

Take a deep breath. Plan things out in pseudo-code first. It'll make it so much easier.

Class Tank
Methods: 
__init__
Draw
Update
Fire

Class Bullet
Methods:
__init__
Draw
Update


Of course, then there is the matter of how this all plugs into the game. How do you keep track of the bullets the tank fires? (Maybe with a list? A vector? Array?). Then you need to call Update() in your game's Update method, and Draw in your Draw method and so on. Good luck!
"I will personally burn everything I've made to the fucking ground if I think I can catch them in the flames."
~ Gabe

"I don't mean to rush you but you are keeping two civilizations waiting!"
~ Cavil, BSG.
"If it's really important to you that other people follow your True Brace Style, it just indicates you're inexperienced. Go find something productive to do."
~ Bregma

"Well, you're not alone.

There's a club for people like that. It's called Everybody and we meet at the bar."

~ Antheus


#16 colts18   Members   -  Reputation: 100

Like
0Likes
Like

Posted 07 February 2011 - 04:13 PM

Ok I still don't fully understand the fire() but I tried, it still doesn't work but is this closer?

class Tank:

    def __init__(self):
        self.tank = pygame.image.load("tank.png")
        self.x = -200
        self.y = 20
    def draw(self, surface):
        surface.blit(self.tank, (self.x, self.y))
    def update():
        self.tank.Update()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                self.fire()
    def fire():
        if self.fire():
            __init__(bullet)
            
        
class Bullet:
    def __init__(self):
        self.bullet = pygame.image.load("tank_bullet.png")
        self.y = tank.y
        self.x = tank.x
        self.speed = 10
        right = self.x + 5
    def draw(self, surface):
        surface.blit(self.x, self.y)
    def update():
        self.bullet.Update()
        self.x += self.x, right * self.speed * 30
        self.y += self.y, right * self.speed * 30

I am also starting to think there could be a problem in the main loop:

pygame.init()                                               	
background_color = (0,0,0)                                      
(width, height) = (640, 480)                                    
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Game Window')                   	
clock = pygame.time.Clock()
tank = Tank()
lvl_1 = Lvl_1()
bullet = Bullet()
enemy_tank = Enemy_tank()
pygame.key.set_repeat(1,50)                                 	
running = True               	
    
while running:

    screen.fill (background_color)
    tank.draw(screen)
    lvl_1.draw(screen)
    enemy_tank.draw(screen)
    pygame.display.flip()                               	
    clock.tick(30)                                          

    for event in pygame.event.get():                        


            if event.type == pygame.QUIT:               	
                        running = False
            elif event.type == pygame.KEYDOWN:              
                    if event.key == pygame.K_RIGHT:
                            tank.x += 5                 	
                    if event.key == pygame.K_LEFT:
                            tank.x -= 5


#17 Burnt_Fyr   Members   -  Reputation: 560

Like
0Likes
Like

Posted 07 February 2011 - 06:53 PM

Ok I still don't fully understand the fire() but I tried, it still doesn't work but is this closer?

class Tank:

    def __init__(self):
        self.tank = pygame.image.load("tank.png")
        self.x = -200
        self.y = 20
    	self.firecountdown=0 # this will make sure you only fire once in a while, not every key repeat

    def draw(self, surface):
        surface.blit(self.tank, (self.x, self.y))

	def update(dt):
     	# this dt is the same one passed when update is called and represents the number of milliseconds elapsed since last frame
     	if(self.firecountdown > 0) # if we are still reloading, 
          	self.firecountdown-= dt #lower the firecountdown by time elapsed.
    	
    def fire():
      	if(self.firecountdown <=0) : # only fire if we are not reloading
      	bullet.x = tank.x
      	bullet.y = tank.y
      	bullet.speed = 10
      	self.firecountdown = 1000 # since we fired, we need to reload. lets reload for 1000ms

  	
        
class Bullet:
    def __init__(self):
        self.bullet = pygame.image.load("tank_bullet.png")
        self.y = tank.y
        self.x = tank.x
        self.speed = 0
        self.forwardx = 1
    	self.forwardy = 0
    def draw(self, surface):
        surface.blit(self.x, self.y)
    def update(dt):
    	self.x += self.forwardx * self.speed/1000 # new x coord = old + forwardx * speed * time
        self.y += self.forwardy * self.speed/1000 # new y coord is similar

I am also starting to think there could be a problem in the main loop:

pygame.init()                                           		
background_color = (0,0,0)                                      
(width, height) = (640, 480)                                    
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Game Window')               		
clock = pygame.time.Clock()
tank = Tank()
lvl_1 = Lvl_1()
bullet = Bullet()
enemy_tank = Enemy_tank()
pygame.key.set_repeat(1,50)                             		
running = True           		
    
while running:

     # this will store the time since last frame in the variable dt for use.
	dt =clock.tick(30)
    
	# Update the game state, including all entities/bullets/etc
	tank.update(dt)
    enemy_tank.update(dt)
	bullet.update(dt)
     
	# the game state is up to date, so lets draw it
	screen.fill (background_color)
   
    lvl_1.draw(screen)
 	tank.draw(screen)
	bullet.draw(screen)
    enemy_tank.draw(screen)
    pygame.display.flip()                           		
 	                                   	

    for event in pygame.event.get():                        


            if event.type == pygame.QUIT:           		
                        running = False
            elif event.type == pygame.KEYDOWN:              
                    if event.key == pygame.K_RIGHT:
                            tank.x += 5             		
                    if event.key == pygame.K_LEFT:
                            tank.x -= 5
                    # added detection for the spacebar, making tank fire bullet
                	if event.key == pygame.K_SPACE: 
                        	tank.fire()


I know i'm beating a dead horse here, but what is tank.self.fire()? you really... really... really need to understand the fundamentals of programming, python, and logic better before you attempt to make a game. I've edited your source as best as i can(Still don't know python, but 20 minutes on google helped, and i really should learn it anyway, for my own use at some point) and commented as much as I deemed necessary. Rather than starting a new thread when you've got this working, keep posting to this one so as not to clutter the forums. Hopefully if someone else is stuck at the same point you are, they will learn from this as well.

#18 colts18   Members   -  Reputation: 100

Like
0Likes
Like

Posted 07 February 2011 - 07:20 PM

Ok I have made the changes and everything is good except there is an error with the tank.update(dt), enemy_tank.update(dt), and bullet.update(dt) and I have tried some changes and I googled it but I still can't figure it out do you know how? This is the error:

Traceback (most recent call last):
File "/home/bolt/Python/game.py", line 71, in <module>
tank.update(dt)
AttributeError: Tank instance has no attribute 'update'

#19 Burnt_Fyr   Members   -  Reputation: 560

Like
0Likes
Like

Posted 07 February 2011 - 08:20 PM

Ok I have made the changes and everything is good except there is an error with the tank.update(dt), enemy_tank.update(dt), and bullet.update(dt) and I have tried some changes and I googled it but I still can't figure it out do you know how? This is the error:

Traceback (most recent call last):
File "/home/bolt/Python/game.py", line 71, in <module>
tank.update(dt)
AttributeError: Tank instance has no attribute 'update'


hmmm... Can you repost the entire source file(copy and paste prefered) as it is now so I can have a looksee?

#20 colts18   Members   -  Reputation: 100

Like
0Likes
Like

Posted 08 February 2011 - 02:08 PM

Here it is:

import pygame

class Tank:

    def __init__(self):
        self.tank = pygame.image.load("tank.png")
        self.x = -200
        self.y = 20
        self.firecountdown=0 # this will make sure you only fire once in a while, not every key repeat

    def draw(self, surface):
        surface.blit(self.tank, (self.x, self.y))

        def update(dt):
        # this dt is the same one passed when update is called and represents the number of milliseconds elapsed since last frame
            if(self.firecountdown > 0):
                self.firecountdown-= dt #lower the firecountdown by time elapsed.
        
    def fire():
        if(self.firecountdown <=0) : # only fire if we are not reloading
            bullet.x = tank.x
            bullet.y = tank.y
            bullet.speed = 10
            self.firecountdown = 1000 # since we fired, we need to reload. lets reload for 1000ms

        
        
class Bullet:
    def __init__(self):
        self.bullet = pygame.image.load("tank_bullet.png")
        self.y = tank.y
        self.x = tank.x
        self.speed = 0
        self.forwardx = 1
        self.forwardy = 0
    def draw(self, surface):
        surface.blit(self.x, self.y)
    def update(dt):
        self.x += self.forwardx * self.speed/1000 # new x coord = old + forwardx * speed * time
        self.y += self.forwardy * self.speed/1000 # new y coord is similar
        
        
        
class Lvl_1:
    
    def __init__(self):
        self.floor = pygame.image.load("floor.png")
    def draw(self, surface):
        surface.blit(self.floor, (0, 0))

class Enemy_tank:

    def __init__(self):
        self.enemy_tank = pygame.image.load("enemy_tank.png")
    def draw(self, surface):
        surface.blit(self.enemy_tank, (220, -40))

pygame.init()                                                   
background_color = (0,0,0)                                      
(width, height) = (640, 480)                                    
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Game Window')                       
clock = pygame.time.Clock()
tank = Tank()
lvl_1 = Lvl_1()
bullet = Bullet()
enemy_tank = Enemy_tank()
pygame.key.set_repeat(1,50)                                     
running = True                   
    
tank.update(dt)
enemy_tank.update(dt)
bullet.update(dt)
     
        # the game state is up to date, so lets draw it
screen.fill (background_color)

lvl_1.draw(screen)
tank.draw(screen)
bullet.draw(screen)
enemy_tank.draw(screen)
pygame.display.flip()                                       
                                                

for event in pygame.event.get():                        


        if event.type == pygame.QUIT:                       
                        running = False
        elif event.type == pygame.KEYDOWN:              
                if event.key == pygame.K_RIGHT:
                            tank.x += 5                         
                if event.key == pygame.K_LEFT:
                            tank.x -= 5
                # added detection for the spacebar, making tank fire bullet
                if event.key == pygame.K_SPACE:
                    tank.fire()






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS