Hey guys I cannot figure out how to add collision detection can someone explain how I just want my tank to stop moving when it hits the other tank. Can anyone help? Thanks.
ret801 -9 Light Poster
and IF statement would remedy this !
Ene Uran commented: simply BS -3
woooee 814 Nearly a Posting Maven
pygame has collision detection. Google is your friend. Even it you can't find an answer for your specific object, you can see how it is done with other objects.
raptr_dflo 48 Posting Pro
pseudocode:
simulation_loop:
new_time = old_time + time_step
new_tank_pos = ComputeTankPos(tank_velocity, new_time)
if new_tank_pos is too close to wall, other tank, whatever else:
new_tank_pos = old_tank_pos
tank_velocity = (0, 0) # if you have velocity separated into x and y components
colts18 0 Newbie Poster
I have spent the last week and a half trying to get this to work; I get no errors when I run this, but the tanks still go through each other.
Here is the code for the entire game:
import pygame
import math
class Tank(pygame.sprite.Sprite):
def __init__(self, init_pos, is_npc=True):
pygame.sprite.Sprite.__init__(self)
self.Tank = pygame.image.load("tank.png")
self.x = -200
self.y = 20
self.firecountdown=0
self.center = init_pos
self.rect = self.Tank.get_rect()
self.velocity = [0, 0]
self.is_npc = bool(is_npc)
def _can_move_to(self, new_rect):
for sprite in self.groups()[0]:
if sprite is not self:
return not sprite.rect.colliderect(new_rect)
def draw(self, surface):
surface.blit(self.Tank, (self.x, self.y))
def update(self, dt,):
keys = pygame.key.get_pressed()
if not self.is_npc:
if keys[pygame.K_RIGHT]:
self.velocity[0] = 250
elif keys[pygame.K_LEFT]:
self.velocity[0] = -250
else:
self.velocity[0] = 0
velocity = [v * t_passed for v in self.velocity]
if self._can_move_to(self.rect.move(*velocity)):
self.rect.move_ip(*velocity)
if(self.firecountdown > 0):
self.firecountdown-= dt
def fire(self, bullet):
if(self.firecountdown <=0) :
bullet.x = self.x
bullet.y = self.y
bullet.fired = True
bullet.speed = 10
self.firecountdown = 1000
class Bullet(pygame.sprite.Sprite):
def __init__(self):
self.bullet = pygame.image.load("tank_bullet.png")
self.y = 0
self.x = 0
self.speed = 0
self.forwardx = 1
self.forwardy = 0
self.fired = False
def draw(self, surface):
surface.blit(self.bullet, (self.x, self.y))
def update(self, dt):
self.x += self.forwardx * self.speed
self.y += self.forwardy * self.speed
if self.x > 640:
self.fired = False
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(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.x = 200
self.y = -40
self.enemy_tank = pygame.image.load("enemy_tank.png")
self.rect = self.enemy_tank.get_rect()
def draw(self, surface):
surface.blit(self.enemy_tank, (self.x, self.y))
def update(self, dt):
pass
class Enemy_bullet(pygame.sprite.Sprite):
pass
tanks = pygame.sprite.Group()
tanks.add (Tank((100, 150), False))
tanks.add (Tank((300, 150)))
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()
t_passed = clock.tick(30)
Tank = Tank(pygame.sprite.Sprite)
lvl_1 = Lvl_1()
bullet = Bullet()
enemy_tank = Enemy_tank()
enemy_bullet = Enemy_bullet()
pygame.key.set_repeat(1,50)
running = True
speed = 100
t_accumalator = 0.0
t_step = 0.01
while running:
t_accumalator += clock.tick() / 1000.0
for t in tanks:
t.update(t_passed)
bullet.update(t_passed)
screen.fill (background_color)
Tank.draw(screen)
lvl_1.draw(screen)
if bullet.fired == True:
bullet.draw(screen)
enemy_tank.draw(screen)
pygame.display.flip()
clock.tick(30)
pygame.event.pump()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
Tank.x += 5
if event.key == pygame.K_LEFT:
Tank.x -= 5
if event.key == pygame.K_SPACE:
Tank.fire(bullet)
while t_accumalator >= t_step:
for tank in tanks:
tank.update(t_step, keys)
t_accumalator -= t_step
pygame.display.flip()
TrustyTony 888 pyMod Team Colleague Featured Poster
Are you afraid to read the documentation?
http://pygame.org/docs/tut/SpriteIntro.html
http://pygame.org/project-Bouncy+Ball+tank-864-.html
Edited by TrustyTony because: n/a
raptr_dflo 48 Posting Pro
There's so much weird stuff in your code now, I'm not sure where to begin. But I'll start with line 106 above, where you assign a new Tank
instance with the same name as the class, making the class inaccessible from that point forward. You also create new tanks by passing a position tuple and assigning it to center
, and then using x
and y
everywhere else. Maybe the pygame.sprite.Sprite class uses center
? If so, save yourself a lot of headache and use it also. Finally it looks like you're using the right and left arrow keys to change the driection of the non-npc tank starting at line 32, and also to tweak the position of your poorly-named Tank instance starting at line 145. One or the other is presumably in a debugging state, but consider commenting out or removing code you're not testing, until you get basics working, and then add it back in when you're ready to proceed to the next step.
colts18 0 Newbie Poster
I watched the Python tutorials at thenewboston.com and made some changes in the code, I got an error with the tank.center but I put a self.center in the tank class? Can anyone give me some hints?
import pygame
import math
class tank(pygame.sprite.Sprite):
def __init__(self, init_pos, is_npc=True):
pygame.sprite.Sprite.__init__(self)
self.Tank = pygame.image.load("tank.png")
self.x = -200
self.y = 20
self.firecountdown=0
self.center = init_pos
self.rect = self.Tank.get_rect()
self.velocity = [0, 0]
self.is_npc = bool(is_npc)
def _can_move_to(self, new_rect):
for sprite in self.groups()[0]:
if sprite is not self:
return not sprite.rect.colliderect(new_rect)
def draw(self, surface):
surface.blit(self.Tank, (self.x, self.y))
def update(self, dt,):
#keys = pygame.key.get_pressed()
#if not self.is_npc:
# if keys[pygame.K_RIGHT]:
# self.velocity[0] = 250
# elif keys[pygame.K_LEFT]:
# self.velocity[0] = -250
# else:
# self.velocity[0] = 0
velocity = [v * t_passed for v in self.velocity]
if self._can_move_to(self.rect.move(*velocity)):
self.rect.move_ip(*velocity)
if(self.firecountdown > 0):
self.firecountdown-= dt
def fire(self, bullet):
if(self.firecountdown <=0) :
bullet.x = self.x
bullet.y = self.y
bullet.fired = True
bullet.speed = 10
self.firecountdown = 1000
class Bullet(pygame.sprite.Sprite):
def __init__(self):
self.bullet = pygame.image.load("tank_bullet.png")
self.y = 0
self.x = 0
self.speed = 0
self.forwardx = 1
self.forwardy = 0
self.fired = False
def draw(self, surface):
surface.blit(self.bullet, (self.x, self.y))
def update(self, dt):
self.x += self.forwardx * self.speed
self.y += self.forwardy * self.speed
if self.x > 640:
self.fired = False
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(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.x = 200
self.y = -40
self.enemy_tank = pygame.image.load("enemy_tank.png")
self.rect = self.enemy_tank.get_rect()
def draw(self, surface):
surface.blit(self.enemy_tank, (self.x, self.y))
def update(self, dt):
pass
class Enemy_bullet(pygame.sprite.Sprite):
pass
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()
t_passed = clock.tick(30)
Tank = tank(pygame.sprite.Sprite)
lvl_1 = Lvl_1()
bullet = Bullet()
enemy_tank = Enemy_tank()
enemy_bullet = Enemy_bullet()
pygame.key.set_repeat(1,50)
running = True
speed = 100
t_accumalator = 0.0
t_step = 0.01
tanks = pygame.sprite.Group()
tanks.add (tank(((tank.center)), False))
while running:
t_accumalator += clock.tick() / 1000.0
for t in tanks:
t.update(t_passed)
bullet.update(t_passed)
screen.fill (background_color)
Tank.draw(screen)
lvl_1.draw(screen)
if bullet.fired == True:
bullet.draw(screen)
enemy_tank.draw(screen)
pygame.display.flip()
clock.tick(30)
pygame.event.pump()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
Tank.x += 5
Tank.velocity[0] = 250
if event.key == pygame.K_LEFT:
Tank.x -= 5
Tank.velocity[0] = -250
if event.key == pygame.K_SPACE:
Tank.fire(bullet)
while t_accumalator >= t_step:
for tank in tanks:
tank.update(t_step, keys)
t_accumalator -= t_step
pygame.display.flip()
raptr_dflo 48 Posting Pro
Now your tank.update() method apparently moves the rect of the sprite, but the tank.draw() method blits the image at (self.x, self.y), which aren't updated except for the player's tank (via keystroke). If you're going to maintain these values separately, you have to keep them synchronized: whenever you move the rect, update x and y; and vice versa.
You can save yourself most of the confusion by writing smaller programs first: one that allows you to use the keyboard to move your own tank the way you want, and a second one that demonstrates automatic movement of [enemy] tanks. Then when you have both programs working correctly separately, then you can look at merging the main loop into one that takes user input for the player-tank and automates enemy-tanks.
For starters, just have two separate classes: PlayerTank and EnemyTank. Then when you're more comfortable, you can put all the common repeated functionality (like the draw() method, for instance) into a BaseTank class, derive PlayerTank and EnemyTank from BaseTank, and add only the new unique members and methods to each of the derived classes.
If anything can move diagonally, there are some good comments under rect.move() and rect.move_ip() at http://www.pygame.org/docs/ref/rect.html#Rect.move
Be a part of the DaniWeb community
We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.