I got the bullets to shoot but the player rect is not aligned with the player itself, so the bullets doesn't come from the player but rather from the rect that is offset.
The 3 main Classes:
(bullet, camera and player)
def RelRect(char, camera):
return Rect(char.rect.x - camera.rect.x, char.rect.y - camera.rect.y, char.rect.w, char.rect.h)
class Camera(object):
'''Class for center screen on the player'''
def __init__(self, screen, player, levelWidth, levelHeight):
self.player = player
self.rect = screen.get_rect()
self.rect.center = self.player.center
self.worldRect = Rect(0, 0, levelWidth, levelHeight)
def update(self):
if self.player.centerx > self.rect.centerx:
self.rect.centerx = self.player.centerx
if self.player.centerx < self.rect.centerx:
self.rect.centerx = self.player.centerx
if self.player.centery > self.rect.centery:
self.rect.centery = self.player.centery
if self.player.centery < self.rect.centery:
self.rect.centery = self.player.centery
def draw_sprites(self, surface, sprites):
for sprite in sprites:
if sprite.rect.colliderect(self.rect):
surface.blit(sprite.image, RelRect(sprite, self))
class Bullet():
def __init__(self, x, y, targetX, targetY):
self.image = ''
self.origX = x
self.origY = y
self.x = x
self.y = y
self.targetX = targetX
self.targetY = targetY
self.image = image.load('res/attack/attack.png')
self.vel = 20
# rnge is the range of the bullet, in frames
self.rnge = 50
# prog is the progress of the bullet, in frames
self.prog = 0
# dmg is the damage that the bullet will do upon impact
self.dmg = 1
self.dmg_mult = 1
# deathtick is the timer for enemy death
self.deathTick = 0
# rect is the hitbox of the bullet
self.w, self.h = self.image.get_width(), self.image.get_height()
self.rect = Rect(self.x, self.y, self.w, self.h)
def update(self):
# Increases Progress of the bullet
if not (sqrt((self.targetX - self.origX) ** 2 + (self.targetY - self.origY) ** 2)) == 0:
self.x += int((self.vel) * (self.targetX - self.origX) /
(sqrt((self.targetX - self.origX) ** 2 +
(self.targetY - self.origY) ** 2)))
self.y += int((self.vel) * (self.targetY - self.origY) /
(sqrt((self.targetX - self.origX) ** 2 +
(self.targetY - self.origY) ** 2)))
self.rect.center = [self.x, self.y]
def check(self, enemies):
# Checks if the bullet is out of range, then deletes it, if it is
if self.prog >= self.rnge:
bullets.remove(self)
#checks if bullets are out of bounds
elif not 0 < self.x < WIDTH - self.w or not 0 < self.y < HEIGHT - self.h:
bullets.remove(self)
else:
#checks if bullet hits target hitbox, if so, starts a timer that kills the bullet after 1 frame
for e in enemies:
if self.rect.colliderect(e.hitbox):
self.deathTick += 1
if self.deathTick > 1:
bullets.remove(self)
#draws each bullet
def draw(self):
screen.blit(self.image, self.rect)
#draws bullet hitboxes
def debug(self):
draw.rect(screen, (0,0,0), self.rect, 2)
draw.line(screen, (255,255,255), (self.x, self.y), (self.targetX, self.targetY), 4)
class Player(sprite.Sprite):
'''class for player and collision'''
def __init__(self, x, y):
sprite.Sprite.__init__(self)
self.moveUnitsY = 0
self.moveUnitsX = 0
self.x = x
self.y = y
self.ground = False
self.jump = False
self.image = image.load("res/move/Ridle.png").convert()
self.rect = self.image.get_rect()
self.Lrun = ["res/move/L1.png",
"res/move/L2.png",
"res/move/L3.png",
"res/move/L4.png",
"res/move/L5.png",
"res/move/L6.png"]
self.Rrun = ["res/move/R1.png",
"res/move/R2.png",
"res/move/R3.png",
"res/move/R4.png",
"res/move/R5.png",
"res/move/R6.png"]
self.direction = "right"
self.rect.topleft = [x, y]
self.frame = 0
def update(self, up, down, left, right):
if up:
if self.ground:
if self.direction == "right":
self.image = image.load("res/move/Ridle.png")
self.jump = True
self.moveUnitsY -= 20
if down:
if self.ground and self.direction == "right":
self.image = image.load("res/move/Ridle.png").convert_alpha()
if self.ground and self.direction == "left":
self.image = image.load("res/move/Lidle.png").convert_alpha()
if not down and self.direction == "right":
self.image = image.load("res/move/Ridle.png").convert_alpha()
if not down and self.direction == "left":
self.image = image.load("res/move/Lidle.png").convert_alpha()
if left:
self.direction = "left"
self.moveUnitsX = -vel
if self.ground:
self.frame += 1
self.image = image.load(self.Lrun[self.frame]).convert_alpha()
if self.frame == 4: self.frame = 0
else:
self.image = self.image = image.load("res/move/Lidle.png").convert_alpha()
if right:
self.direction = "right"
self.moveUnitsX = +vel
if self.ground:
self.frame += 1
self.image = image.load(self.Rrun[self.frame]).convert_alpha()
if self.frame == 4: self.frame = 0
else:
self.image = self.image = image.load("res/move/Ridle.png").convert_alpha()
if not (left or right):
self.moveUnitsX = 0
self.rect.right += self.moveUnitsX
self.collide(self.moveUnitsX, 0, world)
if not self.ground:
self.moveUnitsY += 0.3
if self.moveUnitsY > 10:
self.moveUnitsY = 10
self.rect.top += self.moveUnitsY
if self.jump:
self.moveUnitsY += 2
self.rect.top += self.moveUnitsY
if self.ground == True:
self.jump = False
self.ground = False
self.collide(0, self.moveUnitsY, world)
def collide(self, moveUnitsX, moveUnitsY, world):
self.ground = False
for pos in world:
if self.rect.colliderect(pos):
if moveUnitsX > 0:
self.rect.right = pos.rect.left
if moveUnitsX < 0:
self.rect.left = pos.rect.right
if moveUnitsY > 0:
self.rect.bottom = pos.rect.top
self.moveUnitsY = 0
self.ground = True
if moveUnitsY < 0:
self.rect.top = pos.rect.bottom
self.moveUnitsY = 0
and then the running loop:
while running:
for evnt in event.get():
if evnt.type == QUIT or evnt.type == KEYDOWN and evnt.key == K_ESCAPE:
running = False
if evnt.type == KEYDOWN and evnt.key == K_UP:
up = True
if evnt.type == KEYDOWN and evnt.key == K_DOWN:
down = True
if evnt.type == KEYDOWN and evnt.key == K_LEFT:
left = True
if evnt.type == KEYDOWN and evnt.key == K_RIGHT:
right = True
if evnt .type == MOUSEBUTTONDOWN:
# checks if any mouse button is down, if so sets clicking to true
button = evnt.button
#startTicks = time.get_ticks()
if evnt.type == MOUSEBUTTONUP:
# checks if any mouse button is down, if so sets clicking to true
button = 0
if evnt.type == MOUSEMOTION:
# sets mx and my to mouse x backgand y if mouse is moving
mx, my = evnt.pos
if evnt.type == KEYUP and evnt.key == K_UP:
up = False
if evnt.type == KEYUP and evnt.key == K_DOWN:
down = False
if evnt.type == KEYUP and evnt.key == K_LEFT:
left = False
if evnt.type == KEYUP and evnt.key == K_RIGHT:
right = False
if button == 1:
bullets.append(Bullet(player.rect[0]+ player.rect[2]//2, player.rect[1] + player.rect[3]//2, mx, my))
asize = ((screen_rect.w // background_rect.w + 1) * background_rect.w, (screen_rect.h // background_rect.h + 1) * background_rect.h)
bg = Surface(asize)
for x in range(0, asize[0], background_rect.w):
for y in range(0, asize[1], background_rect.h):
screen.blit(background, (x, y))
for b in bullets:
b.update()
b.draw()
b.check(enemies)
time_spent = sec(clock, FPS)
camera.draw_sprites(screen, all_sprite)
draw.rect(screen, (255,0,0), player.rect, 4)
player.update(up, down, left, right)
camera.update()
display.flip()
if you run the program itself, you can see that the red rectangle (4th last line) that represents the player rect is not to where the character is suppose to appear....
How can I make it so that the player rect will be at the position of the character? So that the bullets come from the player.
Thanks :)
Full Code Here:
https://pastebin.com/z1LwxYYt
The problem with your code is that neither your red rectangle nor the bullets are drawn to the screen in relation to the camera.
The Bullet class should subclass Sprite, too, so you can add them to the all_sprite-group, like you do with the obstacles and the player.
Then let the Camera-class handle the drawing of the bullets.
As for the red rectangle, I suggest removing the RelRect function and move it into the Camera class itself, like this:
class Camera(object):
...
def translate(self, rect):
return Rect(rect.x - self.rect.x, rect.y - self.rect.y, rect.w, rect.h)
def draw_sprites(self, surface, sprites):
for sprite in sprites:
if sprite.rect.colliderect(self.rect):
surface.blit(sprite.image, self.translate(sprite.rect, self))
which would allow you to draw the rect like this:
draw.rect(screen, (255,0,0), camera.translate(player.rect), 4)
Related
I'm working on python project right now using pygame library and I need help with this project I make. I want my tank to shoot bullets and so those bullets ricochet from the walls. What is the best way possible to do this?
I'm sorry that my code looks so messy, I've been watching different youtube tutorials and they all do differently.
Here is my code
import pygame
pygame.init()
# ======================= Variables =======================
# ------------------------ Screen -------------------------
screenWidth = 1060
screenHeight = 798
screenSize = (screenWidth, screenHeight)
display = pygame.display.set_mode((screenWidth, screenHeight))
pygame.display.set_caption("Tank game")
bg = pygame.image.load("sprites/background/background1.png")
bg = pygame.transform.scale(bg, (screenWidth, screenHeight))
# ------------------------ Player -------------------------
# ------------------------ Enemy -------------------------
# ----------------------- Other ---------------------------
red = (155, 0, 0)
clock = pygame.time.Clock()
fps = 60
# ========================= Clases ========================
class player(pygame.sprite.Sprite):
def __init__(self, location, angle, vel, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("sprites/player/player_tank.png")
self.x = x
self.y = y
self.vel = vel
self.angle = angle
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
if self.angle == 360:
self.angle = 0
def rotate(self):
rot_image = pygame.transform.rotate(self.image, self.angle)
rot_rect = rot_image.get_rect(center=self.rect.center)
return rot_image, rot_rect
def moving_after_angle_change(self):
x = round(math.cos(math.radians(self.angle + 90)), 1) * self.vel
y = round(math.sin(math.radians(self.angle - 90)), 1) * self.vel
return x, y
class enemy(pygame.sprite.Sprite):
def __init__(self, x, y, width, height, end):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("sprites/enemy/enemy_tank.png")
self.x = x
self.y = y
self.width = width
self.height = height
self.end = end
self.path = [self.x, self.y, self.end]
self.vel = 5
def draw(self, display):
self.move()
display.blit(self.image, (self.x, self.y))
def move(self):
if self.vel > 0:
pass
# Bullet
bullet = pygame.image.load("sprites/bullet/bullet.png")
bullet = pygame.transform.scale(bullet, (16, 16))
bullet_x = 0
bullet_y = 480
bullet_x_change = 0
bullet_y_change = 10
bullet_state = 'ready'
# ======================= Functions =======================
def redrawGameWindow():
display.blit(bg, (0, 0))
display.blit(player_tank.image, player_tank.rect)
display.blit(enemy_tank.image, (enemy_tank.x, enemy_tank.y))
#display.blit(bullet, (player_tank.x + 160, player_tank.y + 100))
pygame.display.flip()
def fireBullet(x, y):
global bullet_state
bullet_state = 'fire'
display.blit(bullet, (x + 16, y + 10))
player_location = [70, 570]
player_angle = 270
player_angle_change = 0
player_vel = 0
player_x_change = 0
player_y_change = 0
player_tank_x_change_store = 0
player_tank_y_change_store = 0
run = True
while run:
clock.tick(fps)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
player_vel = 2
elif event.key == pygame.K_DOWN:
player_vel = -2
elif event.key == pygame.K_LEFT:
player_angle_change = 2
elif event.key == pygame.K_RIGHT:
player_angle_change = -2
if event.key == pygame.K_SPACE:
display.blit(bullet, (player_tank.x + 160, player_tank.y + 100))
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
player_vel = 0
elif event.key == pygame.K_DOWN:
player_vel = 0
elif event.key == pygame.K_LEFT:
player_angle_change = 0
elif event.key == pygame.K_RIGHT:
player_angle_change = 0
player_angle += player_angle_change
player_tank = player(player_location, player_angle, player_vel, player_x_change, player_y_change)
enemy_tank = enemy(800, 170, 64, 64, 700)
player_tank.image, player_tank.rect = player_tank.rotate()
player_tank.x_change, player_tank.y_change = player_tank.moving_after_angle_change()
player_tank_x_change_store += player_tank.x_change
player_tank_y_change_store += player_tank.y_change
player_tank.rect.centerx += player_tank_x_change_store
player_tank.rect.centery += player_tank_y_change_store
# Bullet movement
if bullet_state == "fire":
fireBullet(player_tank.x, bullet_y)
bullet_y -= bullet_y_change
redrawGameWindow()
pygame.quit()
quit()
One way to do this is to make the bullets velocity flip when it hits a wall. Now I'm assuming the walls are the edge of the screen so what you need to do is in the loop, check if the bullet is about to hit a wall (the edge of the screen) and if it is, flip its x_change and y_change. So something like this:
if bullet_y <= 0:
bullet_y_change *= -1
bullet_y = 0
if bullet_y >= screenHeight:
bullet_y_change *= -1
bullet_y = screenHeight
if bullet_x <= 0:
bullet_x_change *= -1
bullet_x = 0
if bullet_x >= screenWidth:
bullet_x_change *= 1
bullet_x = screenWidth
Here's a full example, based on an old answer:
import pygame
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((32, 32))
self.image.fill((0, 0, 0))
self.image.set_colorkey((0, 0, 0))
pygame.draw.polygon(self.image, pygame.Color('dodgerblue'), ((0, 0), (32, 16), (0, 32)))
self.org_image = self.image.copy()
self.angle = 0
self.direction = pygame.Vector2(1, 0)
self.rect = self.image.get_rect(center=(200, 200))
self.pos = pygame.Vector2(self.rect.center)
def update(self, events, dt):
for e in events:
if e.type == pygame.KEYDOWN:
if e.key == pygame.K_SPACE:
self.groups()[0].add(Projectile(self.rect.center, self.direction.normalize()))
pressed = pygame.key.get_pressed()
if pressed[pygame.K_a]:
self.angle += 3
if pressed[pygame.K_d]:
self.angle -= 3
self.direction = pygame.Vector2(1, 0).rotate(-self.angle)
self.image = pygame.transform.rotate(self.org_image, self.angle)
self.rect = self.image.get_rect(center=self.rect.center)
class Projectile(pygame.sprite.Sprite):
def __init__(self, pos, direction):
super().__init__()
self.image = pygame.Surface((8, 8))
self.image.fill((0, 0, 0))
self.image.set_colorkey((0, 0, 0))
pygame.draw.circle(self.image, pygame.Color('orange'), (4, 4), 4)
self.rect = self.image.get_rect(center=pos)
self.direction = direction
self.pos = pygame.Vector2(self.rect.center)
self.lives = 15
def update(self, events, dt):
# Bounding box of the screen
screen_r = pygame.display.get_surface().get_rect()
# where we would move next
next_pos = self.pos + self.direction * dt
# we hit a hall
if not screen_r.contains(self.rect):
# after 15 hits, destroy self
self.lives -= 1
if self.lives == 0:
return self.kill()
# horizontal reflection
if next_pos.x > screen_r.right or next_pos.x < screen_r.left:
self.direction.x *= -1
# vertical reflection
if next_pos.y > screen_r.bottom or next_pos.y < screen_r.top:
self.direction.y *= -1
# move after applying reflection
next_pos = self.pos + self.direction * dt
# set the new position
self.pos = next_pos
self.rect.center = self.pos
def main():
pygame.init()
screen = pygame.display.set_mode((500, 500))
sprites = pygame.sprite.Group(Player())
clock = pygame.time.Clock()
dt = 0
while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
sprites.update(events, dt)
screen.fill((30, 30, 30))
sprites.draw(screen)
pygame.display.update()
dt = clock.tick(60)
if __name__ == '__main__':
main()
See how using the Vector2 class makes this kind of tasks very easy to solve.
Also, look at the proper usage of the Sprite class. Each Sprite minds its own business: the Player class handles rotating the player and creating projectiles, Projectile handles moving the projectiles and bouncing of the wall.
I am trying to make a space invaders/asteroids game where you can shoot in all directions using pygame. Currently, I can move my ship in all directions and shoot in all directions, but as soon as I change directions my bullets that were previously fired will stop moving/move in the direction that the ship is going. Thank you in advance.
import pygame
import random
# intialize the pygame
pygame.init()
# dimensions of the pygame
screen = pygame.display.set_mode((800,600))
# Caption and Icon
pygame.display.set_caption("Saving Earth")
icon = pygame.image.load('ufo.png')
pygame.display.set_icon(icon)
# images
earth_image = pygame.image.load('earth.png')
fly_up = pygame.image.load('spaceshipU.png')
fly_down = pygame.image.load('spaceshipD.png')
fly_left = pygame.image.load('spaceshipL.png')
fly_right = pygame.image.load('spaceshipR.png')
background = pygame.image.load('space.jpg')
clock = pygame.time.Clock()
#Player class
class player(object):
def __init__(self, player_x, player_y, width, height):
self.player_x = player_x
self.player_y = player_y
self.width = width
self.height = height
self.speed = 4
self.left = False
self.right = False
self.up = True
self.down = False
# draws the ship to screen
def draw(self, screen):
if self.left:
screen.blit(fly_left, (self.player_x,self.player_y))
elif self.right:
screen.blit(fly_right, (self.player_x,self.player_y))
elif self.up:
screen.blit(fly_up, (self.player_x,self.player_y))
elif self.down:
screen.blit(fly_down, (self.player_x,self.player_y))
else:
screen.blit(fly_up, (self.player_x,self.player_y))
class Bullet(object):
def __init__(self, bullet_x, bullet_y, radius, color):
self.bullet_x = bullet_x
self.bullet_y = bullet_y
self.radius = radius
self.color = color
self.speed = 6
self.vertfacing = 1
self.hortfacing = 1
def draw(self, screen):
pygame.draw.circle(screen, self.color, (self.bullet_x,self.bullet_y), self.radius)
# redraws game screen
def redraw_game_screen():
screen.blit(background, (0,0))
screen.blit(earth_image, (350, 230))
ship.draw(screen)
for bullet in bullets:
bullet.draw(screen)
pygame.display.update()
#Game Loop
ship = player(300, 300, 32, 32)
bullets = []
vertfacing = -1
hortfacing = 1
running = True
while running:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
for bullet in bullets:
if bullet.bullet_x < 800 and bullet.bullet_x > 0 and bullet.bullet_y < 600 and bullet.bullet_y > 0 :
if hortfacing == -1 and ship.left:
bullet.bullet_x -= bullet.speed
elif hortfacing == 1 and ship.right:
bullet.bullet_x += bullet.speed
elif vertfacing == 1 and ship.down:
bullet.bullet_y += bullet.speed
elif vertfacing == -1 and ship.up:
bullet.bullet_y -= bullet.speed
else:
bullets.remove(bullet)
#key commands
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE]:
if ship.left:
hortfacing = -1
elif ship.right:
hortfacing = 1
elif ship.up:
vertfacing = -1
elif ship.down:
vertfacing = 1
if len(bullets) < 100:
bullets.append(Bullet(round(ship.player_x + ship.width //2), round(ship.player_y + ship.height//2), 6, (255,165,0)))
if keys[pygame.K_LEFT] and ship.player_x > ship.speed:
ship.player_x -= ship.speed
ship.left = True
ship.right = False
ship.up = False
ship.down = False
elif keys[pygame.K_RIGHT] and ship.player_x < 800 - ship.speed - ship.width:
ship.player_x += ship.speed
ship.right = True
ship.left = False
ship.up = False
ship.down = False
elif keys[pygame.K_UP] and ship.player_y > ship.speed:
ship.player_y -= ship.speed
ship.up = True
ship.down = False
ship.left = False
ship.right = False
elif keys[pygame.K_DOWN] and ship.player_y < 600 - ship.height - ship.speed:
ship.player_y += ship.speed
ship.down = True
ship.up = False
ship.left = False
ship.right = False
redraw_game_screen()
pygame.quit()
You have to se the attributes vertfacing and hortfacing in the class Bullet:
class Bullet(object):
def __init__(self, bullet_x, bullet_y, radius, color, vertfacing, hortfacing):
self.bullet_x = bullet_x
self.bullet_y = bullet_y
self.radius = radius
self.color = color
self.speed = 6
self.vertfacing = vertfacing
self.hortfacing = hortfacing
def draw(self, screen):
pygame.draw.circle(screen, self.color, (self.bullet_x,self.bullet_y), self.radius)
Pass the attributes to the constructor when a Bullet spawns:
if len(bullets) < 100:
bullet = Bullet(round(ship.player_x + ship.width //2),
round(ship.player_y + ship.height//2), 6, (255,165,0),
vertfacing, hortfacing)
bullets.append(bullet)
Use the attributes of bullet (bullet.hortfacing, bullet.vertfacing) when you calculate the new position.
Add a method to the class Bullet that moves it:
class Bullet(object):
# [...]
def move(self):
if self.hortfacing == -1:
self.bullet_x -= self.speed
elif self.hortfacing == 1:
self.bullet_x += self.speed
elif self.vertfacing == 1:
self.bullet_y += self.speed
elif self.vertfacing == -1:
self.bullet_y -= self.speed
Call the method for each bullet:
for bullet in bullets:
if bullet.bullet_x < 800 and bullet.bullet_x > 0 and bullet.bullet_y < 600 and bullet.bullet_y > 0 :
bullet.move()
else:
bullets.remove(bullet)
This question already has answers here:
Pygame collision with masks
(1 answer)
Collision between masks in pygame
(1 answer)
Pygame mask collision
(1 answer)
How can I made a collision mask?
(1 answer)
Closed 2 years ago.
I am trying to have a pixel perfect collision with my pong object and my rotated paddle object. However, I realized that the pong ball is still hitting the rectangle of the rotated paddle object. As you can see, the ball is hitting the rect of the paddle, instead of the actual paddle
Here is my pong class with defined collision detection. Please check the checkCollision() function because I use the pygame.sprite.colliderect() function.
class Pong(pygame.sprite.Sprite):
def __init__(self, screensize):
pygame.sprite.Sprite.__init__(self)
self.screensize = screensize
self.centerx = screensize[0] // 2
self.centery = screensize[1] // 2
self.radius = 25
self.rect = pygame.Rect(self.centerx-self.radius,
self.centery-self.radius,
self.radius*2, self.radius*2)
self.image = pygame.image.load("pokeball.png").convert()
self.colorkey = self.image.get_at((0,0))
self.image = pygame.transform.scale(self.image, (self.radius, self.radius))
#Create the mask
self.mask = pygame.mask.from_surface(self.image)
self.color = (100,100,255)
self.direction = [-2,1]
self.speedx = 2
self.speedy = 3
self.hit_edge_left = False
self.hit_edge_right = False
def checkCollision(self, player_paddle, ai_paddle):
col = pygame.sprite.collide_rect(self, player_paddle)
return col
def collisionFormula(self, player_paddle, ai_paddle):
if self.checkCollision(self, player_paddle):
relative_IntersectionY = player_paddle.centery - self.rect.centery
normal_IntersectionY = relative_IntersectionY / (player_paddle.height /2)
bounce_angle = normal_IntersectionY * (5*math.pi/ 12 )
self.direction[0] = math.cos(bounce_angle)
self.direction[1] = -1 * math.sin(bounce_angle)
def update_ball_position(self):
#update the position of the ball
self.centerx += self.direction[0]*self.speedx
self.centery += self.direction[1]*self.speedy
self.rect.center = (self.centerx, self.centery)
def reset_ball(self):
if self.rect.right >= self.screensize[0]-1:
self.hit_edge_right = True
self.__init__(self.screensize)
elif self.rect.left <= 0:
self.hit_edge_left = True
self.__init__(self.screensize)
def collision_checks(self, player_paddle, ai_paddle):
#if the ball hits the top or bottom of the screen, change the y direction
if self.rect.top <= 0 or self.rect.bottom >= self.screensize[1] - 1:
self.direction[1] *= -1
#if the pong hits the paddles, change how the pong ball moves
if self.rect.colliderect(player_paddle.rect) or self.rect.colliderect(ai_paddle.rect):
self.collisionFormula(player_paddle, ai_paddle)
def update(self, player_paddle, ai_paddle):
self.update_ball_position()
self.reset_ball()
self.collision_checks(player_paddle, ai_paddle)
def render(self, screen):
screen.blit(self.image, (self.centerx, self.centery))<!-- Paste the part of the code that shows the problem.
Here is my PlayerPaddle class with defined rotate functions.
class PlayerPaddle(pygame.sprite.Sprite):
def __init__(self, screensize):
pygame.sprite.Sprite.__init__(self)
self.screensize = screensize
self.centerx = 50
self.centery = screensize[1]//2
self.height = 100
self.width = 20
self.imageMaster = pygame.image.load("naruto.png").convert()
self.colorkey = self.imageMaster.get_at((0,0))
self.imageMaster = pygame.transform.scale(self.imageMaster, (100, 200))
self.image = self.imageMaster
#mask
#self.maskMaster = pygame.mask.from_surface(self.image)
#self.mask = self.maskMaster
self.rect = self.image.get_rect()
self.rect.center = (screensize[0]//2, screensize[1]//2)
self.dir = 0
self.color = (100,255,100)
self.speed = 3
self.direction = 0
self.update()
def update(self):
#Rotate functions
oldCenter = self.rect.center
self.image = pygame.transform.rotate(self.imageMaster, self.dir).convert()
self.image.set_colorkey(self.colorkey)
self.rect = self.image.get_rect()
#self.rect.center = oldCenter
self.mask = pygame.mask.from_surface(self.image)
self.centery += self.direction*self.speed
self.rect.center = (self.centerx, self.centery)
if self.rect.top < 0:
self.rect.top = 0
if self.rect.bottom > self.screensize[1]-1:
self.rect.bottom = self.screensize[1]-1
def render(self, screen):
screen.blit(self.image, (self.rect.x, self.rect.y))
def turnLeft(self):
self.dir += 45
if self.dir > 360:
self.dir = 45
def turnRight(self):
self.dir -= 45
if self.dir < 0:
self.dir = 315
And I write this within the while loop of my main().
if pygame.sprite.spritecollide(pong_sprite, paddleGroup, False, pygame.sprite.collide_mask):
print("Collided")
I'm not sure why this is occurring but I'd like to know how to get a pixel perfect collision so I can avoid the issue from the image.
EDIT:
I changed the update function of my PlayerPaddle class.
def update(self):
#Rotate functions
oldCenter = self.rect.center
self.image = pygame.transform.rotate(self.imageMaster, self.dir)
self.rect = self.image.get_rect()
self.rect.center = oldCenter
self.mask = pygame.mask.from_surface(self.image)
self.centery += self.direction*self.speed
self.rect.center = (self.centerx, self.centery)
if self.rect.top < 0:
self.rect.top = 0
if self.rect.bottom > self.screensize[1]-1:
self.rect.bottom = self.screensize[1]-1
And here is my main():
def main():
pygame.init()
screensize = (640,700)
screen = pygame.display.set_mode(screensize)
background = pygame.Surface(screen.get_size())
background.fill((0, 255, 0))
clock = pygame.time.Clock()
pong_sprite = Pong(screensize)
player_paddle = PlayerPaddle(screensize)
ai_paddle = AIPaddle(screensize)
paddleGroup = pygame.sprite.Group()
paddleGroup.add(player_paddle)
pongGroup = pygame.sprite.Group()
pongGroup.add(pong_sprite)
running = True
keymap = {pygame.K_u: False}
while running:
#fps limiting/reporting phase
clock.tick(64)
screen.fill((100,100,100))
#event handling phase
for event in pygame.event.get():
if event.type == QUIT:
running = False
if event.type == KEYDOWN:
if event.key in keymap:
keymap[event.key] = True
if event.key == K_UP:
player_paddle.direction = -1
elif event.key == K_DOWN:
player_paddle.direction = 1
elif event.key == K_LEFT:
player_paddle.turnLeft()
elif event.key == K_RIGHT:
player_paddle.turnRight()
if event.type == KEYUP:
if event.key in keymap:
keymap[event.key] = False
if event.key == K_UP and player_paddle.direction == -1:
player_paddle.direction = 0
elif event.key == K_DOWN and player_paddle.direction == 1:
player_paddle.direction = 0
#object updating phase
ai_paddle.update(pong_sprite, player_paddle)
#player_paddle.update()
#pong.update(player_paddle, ai_paddle)
if pygame.sprite.spritecollide(pong_sprite, paddleGroup, False, pygame.sprite.collide_mask):
print("Collided")
if pong_sprite.hit_edge_left:
print("You won")
#running = False
elif pong_sprite.hit_edge_right:
print("You Lose")
#running = False
#rendering phase
ai_paddle.render(screen)
player_paddle.render(screen)
#pong.render(screen)
paddleGroup.clear(screen, background)
paddleGroup.update()
paddleGroup.draw(screen)
pongGroup.clear(screen,background)
pongGroup.update(player_paddle, ai_paddle)
pongGroup.draw(screen)
pygame.display.flip()
pygame.quit()
Here is my imageenter image description here:
This is the naruto.jpg image
And here is the pokeball.jpg
enter image description here
Hello I am currently making a survival shooter but cannot find any way on how to do my collisions! I am trying to make the player collide with the floors but with no success. Here is an image of the map (I want to collide with moon blocks):
http://i.stack.imgur.com/R2apz.jpg
Here is an image of moon blocks with no Background:
http://i.stack.imgur.com/W9H2m.png
And finally here is my code:
import pygame
import random
gravity = .5
jump_time = 2000
x = 0
y = 0
# Player
class Player(pygame.sprite.Sprite):
def __init__(self, x, y, gravity):
# Player dimensions and position
self.gravity = gravity
# Player image and animation
self.images = []
self.images.append(pygame.image.load('images/player.png'))
self.images.append(pygame.image.load('images/player2.png'))
#~ self.images.append(pygame.image.load('ball1.png'))
#~ self.images.append(pygame.image.load('ball2.png'))
self.maxImage = len(self.images)
self.currentImage = 0
#~ self.rect = pygame.Rect(x, y, 80, 80)
self.rect = self.images[0].get_rect()
self.rect.x = x
self.rect.y = y
self.timeTarget = 10
self.timeNum = 1
self.velX = 0
self.velY = 0
# Jump and gravity
self.vSpeed = 3
self.jumpForce = 15
self.maxVspeed = 3
self.isJumping = False
# Jump inputs
def handle_events(self, event):
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
if not self.isJumping:
self.isJumping = True
elif event.key == pygame.K_a:
self.velX = -5
elif event.key == pygame.K_d:
self.velX = +5
elif event.type == pygame.KEYUP:
if event.key in (pygame.K_a, pygame.K_d):
self.velX = 0
# PLayer updates
def update(self, ground):
keys = pygame.key.get_pressed()
# Jumping
self.vSpeed += gravity
if self.vSpeed > self.maxVspeed:
self.vSpeed = self.maxVspeed
self.rect.y += self.vSpeed
if self.rect.y >= ground.y:
self.vSpeed = 0
self.rect.y = ground.y
self.isJumping = False
if keys[pygame.K_SPACE]:
if not self.isJumping:
self.isJumping = True
if self.isJumping:
if pygame.time.get_ticks() < jump_time:
self.isJumping == True
else:
self.isJumping = False
self.vSpeed -= self.jumpForce
#print "isJumping:", self.isJumping
# Animations
if self.timeNum == self.timeTarget:
self.currentImage += 1
if self.currentImage >= self.maxImage:
self.currentImage = 0
self.timeNum = 0
self.rect.centerx += self.velX
self.rect.centery += self.velY
# Screen wrap
if self.rect.right > 1280:
self.rect.left = 0
elif self.rect.left < 0:
self.rect.right = 1280
# Player rendering
def render(self, surface):
surface.blit(self.images[self.currentImage], self.rect)
#----------------------------------------------------------------------
class Zombie():
def __init__(self, x, y):
self.image = pygame.image.load('images/zombie.png')
#~ self.image = pygame.image.load('ball2.png')
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.direction_left = True
def update(self, surface_rect):
if self.direction_left:
self.rect.x -= 1
if self.rect.left <= surface_rect.left:
self.direction_left = not self.direction_left
else:
self.rect.x += 1
if self.rect.right >= surface_rect.right:
self.direction_left = not self.direction_left
def render(self, surface):
surface.blit(self.image, self.rect)
#----------------------------------------------------------------------
class Background():
def __init__(self):
self.image = pygame.image.load('images/arena2.jpg')
#~ self.image = pygame.image.load('background.jpg')
self.rect = self.image.get_rect()
def render(self, surface):
surface.blit(self.image, self.rect)
#----------------------------------------------------------------------
class Game():
def __init__(self):
pygame.init()
# A few variables
self.gravity = .50
self.ground = pygame.Rect(0, 640, 1280, 80)
# Screen
size = (1280, 720)
self.screen = pygame.display.set_mode(size)
pygame.display.set_caption('Moon Survival!')
# Moon / Background
self.moon = Background()
# Zombies
self.zombies = []
for i in range(10):
self.zombies.append( Zombie(random.randint(0,1280), random.randint(0,720)) )
# Player
self.player = Player(25, 320, self.gravity)
# Font for text
self.font = pygame.font.SysFont(None, 72)
# Pause - center on screen
self.pause_text = self.font.render("PAUSE", -1, (255,0,0))
self.pause_rect = self.pause_text.get_rect(center = self.screen.get_rect().center)
def run(self):
clock = pygame.time.Clock()
# "state machine"
RUNNING = True
PAUSED = False
GAME_OVER = False
# Game loop
while RUNNING:
# (all) Events
for event in pygame.event.get():
if event.type == pygame.QUIT:
RUNNING = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
RUNNING = False
elif event.key == pygame.K_p:
PAUSED = not PAUSED
# Player/Zomies events
if not PAUSED and not GAME_OVER:
self.player.handle_events(event)
# (all) Movements / Updates
if not PAUSED and not GAME_OVER:
self.player.update(self.ground)
for z in self.zombies:
z.update(self.screen.get_rect())
# (all) Display updating
self.moon.render(self.screen)
for z in self.zombies:
z.render(self.screen)
self.player.render(self.screen)
if PAUSED:
self.screen.blit(self.pause_text, self.pause_rect)
pygame.display.update()
# FTP
clock.tick(100)
# --- the end ---
pygame.quit()
#---------------------------------------------------------------------
Game().run()
Any help will be greatly appreciated, thank you.
I made a very similar game for PyWeek #17 called "Miner".
Here's a screenshot: http://media.pyweek.org/dl/17/powrtoch/miner_ss.png (you can see the similarity!)
You can find the relevant code on GitHub here: https://github.com/marcusmoller/pyweek17-miner/blob/master/miner/engine.py#L202-L220:
def checkCollision(self, sprite, xVel, yVel):
for x in range(len(level.levelStructure)):
for y in range(len(level.levelStructure[x])):
block = level.levelStructure[x][y]
if block is not None:
if pygame.sprite.collide_rect(sprite, block):
if xVel < 0:
sprite.rect.x = block.rect.x + block.rect.w
if xVel > 0:
sprite.rect.x = block.rect.x - sprite.rect.w
if yVel < 0:
sprite.rect.y = block.rect.y + block.rect.h
if yVel > 0 and not sprite.onGround:
sprite.onGround = True
sprite.rect.y = block.rect.y - sprite.rect.h
You could do something like this using collide_rect:
# See if the Sprite block collides with anything in the Ground block_list
for block in groundBlocks:
if(collide_rect(player, block)):
# do not fall
else:
# fall
where all Block you can walk on are in the groundBlocks list.
i'd like to add the same collision detection used by the player sprite to the enemy sprites or 'creeps' ive added all the relevant code I can see yet collisons are still not being detected and handled, please find below the class, I have no idea what is wrong currently, the list of walls to collide with is 'wall_list'
import pygame
import pauseScreen as dm
import re
from pygame.sprite import Sprite
from pygame import Rect, Color
from random import randint, choice
from vec2d import vec2d
from simpleanimation import SimpleAnimation
import displattxt
black = (0,0,0)
white = (255,255,255)
blue = (0,0,255)
green = (101,194,151)
global currentEditTool
currentEditTool = "Tree"
global editMap
editMap = False
open('MapMaker.txt', 'w').close()
def draw_background(screen, tile_img):
screen.fill(black)
img_rect = tile_img.get_rect()
global rect
rect = img_rect
nrows = int(screen.get_height() / img_rect.height) + 1
ncols = int(screen.get_width() / img_rect.width) + 1
for y in range(nrows):
for x in range(ncols):
img_rect.topleft = (x * img_rect.width,
y * img_rect.height)
screen.blit(tile_img, img_rect)
def changeTool():
if currentEditTool == "Tree":
None
elif currentEditTool == "Rock":
None
def pauseGame():
red = 255, 0, 0
green = 0,255, 0
blue = 0, 0,255
screen.fill(black)
pygame.display.update()
if editMap == False:
choose = dm.dumbmenu(screen, [
'Resume',
'Enable Map Editor',
'Quit Game'], 64,64,None,32,1.4,green,red)
if choose == 0:
print("hi")
elif choose ==1:
global editMap
editMap = True
elif choose ==2:
print("bob")
elif choose ==3:
print("bob")
elif choose ==4:
print("bob")
else:
None
else:
choose = dm.dumbmenu(screen, [
'Resume',
'Disable Map Editor',
'Quit Game'], 64,64,None,32,1.4,green,red)
if choose == 0:
print("Resume")
elif choose ==1:
print("Dis ME")
global editMap
editMap = False
elif choose ==2:
print("bob")
elif choose ==3:
print("bob")
elif choose ==4:
print("bob")
else:
None
class Wall(pygame.sprite.Sprite):
# Constructor function
def __init__(self,x,y,width,height):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([width, height])
self.image.fill(green)
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
class insertTree(pygame.sprite.Sprite):
def __init__(self,x,y,width,height, typ):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("images/map/tree.png").convert()
self.image.set_colorkey(white)
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
class insertRock(pygame.sprite.Sprite):
def __init__(self,x,y,width,height, typ):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("images/map/rock.png").convert()
self.image.set_colorkey(white)
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
class Creep(pygame.sprite.Sprite):
""" A creep sprite that bounces off walls and changes its
direction from time to time.
"""
change_x=0
change_y=0
def __init__(
self, screen, creep_image, explosion_images,
field, init_position, init_direction, speed):
""" Create a new Creep.
screen:
The screen on which the creep lives (must be a
pygame Surface object, such as pygame.display)
creep_image:
Image (surface) object for the creep
explosion_images:
A list of image objects for the explosion
animation.
field:
A Rect specifying the 'playing field' boundaries.
The Creep will bounce off the 'walls' of this
field.
init_position:
A vec2d or a pair specifying the initial position
of the creep on the screen.
init_direction:
A vec2d or a pair specifying the initial direction
of the creep. Must have an angle that is a
multiple of 45 degres.
speed:
Creep speed, in pixels/millisecond (px/ms)
"""
Sprite.__init__(self)
self.screen = screen
self.speed = speed
self.field = field
self.rect = creep_image.get_rect()
# base_image holds the original image, positioned to
# angle 0.
# image will be rotated.
#
self.base_image = creep_image
self.image = self.base_image
self.explosion_images = explosion_images
# A vector specifying the creep's position on the screen
#
self.pos = vec2d(init_position)
# The direction is a normalized vector
#
self.direction = vec2d(init_direction).normalized()
self.state = Creep.ALIVE
self.health = 15
def is_alive(self):
return self.state in (Creep.ALIVE, Creep.EXPLODING)
def changespeed(self,x,y):
self.change_x+=x
self.change_y+=y
def update(self, time_passed, walls):
""" Update the creep.
time_passed:
The time passed (in ms) since the previous update.
"""
if self.state == Creep.ALIVE:
# Maybe it's time to change the direction ?
#
self._change_direction(time_passed)
# Make the creep point in the correct direction.
# Since our direction vector is in screen coordinates
# (i.e. right bottom is 1, 1), and rotate() rotates
# counter-clockwise, the angle must be inverted to
# work correctly.
#
self.image = pygame.transform.rotate(
self.base_image, -self.direction.angle)
# Compute and apply the displacement to the position
# vector. The displacement is a vector, having the angle
# of self.direction (which is normalized to not affect
# the magnitude of the displacement)
#
displacement = vec2d(
self.direction.x * self.speed * time_passed,
self.direction.y * self.speed * time_passed)
self.pos += displacement
# When the image is rotated, its size is changed.
# We must take the size into account for detecting
# collisions with the walls.
#
self.image_w, self.image_h = self.image.get_size()
bounds_rect = self.field.inflate(
-self.image_w, -self.image_h)
if self.pos.x < bounds_rect.left:
self.pos.x = bounds_rect.left
self.direction.x *= -1
elif self.pos.x > bounds_rect.right:
self.pos.x = bounds_rect.right
self.direction.x *= -1
elif self.pos.y < bounds_rect.top:
self.pos.y = bounds_rect.top
self.direction.y *= -1
elif self.pos.y > bounds_rect.bottom:
self.pos.y = bounds_rect.bottom
self.direction.y *= -1
# collision detection
old_x=bounds_rect.left
new_x=old_x+self.direction.x
bounds_rect.left = new_x
# hit a wall?
collide = pygame.sprite.spritecollide(self, walls, False)
if collide:
# yes
bounds_rect.left=old_x
old_y=self.pos.y
new_y=old_y+self.direction.y
self.pos.y = new_y
collide = pygame.sprite.spritecollide(self, walls, False)
if collide:
# yes
self.pos.y=old_y
elif self.state == Creep.EXPLODING:
if self.explode_animation.active:
self.explode_animation.update(time_passed)
else:
self.state = Creep.DEAD
self.kill()
elif self.state == Creep.DEAD:
pass
#------------------ PRIVATE PARTS ------------------#
# States the creep can be in.
#
# ALIVE: The creep is roaming around the screen
# EXPLODING:
# The creep is now exploding, just a moment before dying.
# DEAD: The creep is dead and inactive
#
(ALIVE, EXPLODING, DEAD) = range(3)
_counter = 0
def _change_direction(self, time_passed):
""" Turn by 45 degrees in a random direction once per
0.4 to 0.5 seconds.
"""
self._counter += time_passed
if self._counter > randint(400, 500):
self.direction.rotate(45 * randint(-1, 1))
self._counter = 0
def _point_is_inside(self, point):
""" Is the point (given as a vec2d) inside our creep's
body?
"""
img_point = point - vec2d(
int(self.pos.x - self.image_w / 2),
int(self.pos.y - self.image_h / 2))
try:
pix = self.image.get_at(img_point)
return pix[3] > 0
except IndexError:
return False
def _decrease_health(self, n):
""" Decrease my health by n (or to 0, if it's currently
less than n)
"""
self.health = max(0, self.health - n)
if self.health == 0:
self._explode()
def _explode(self):
""" Starts the explosion animation that ends the Creep's
life.
"""
self.state = Creep.EXPLODING
pos = ( self.pos.x - self.explosion_images[0].get_width() / 2,
self.pos.y - self.explosion_images[0].get_height() / 2)
self.explode_animation = SimpleAnimation(
self.screen, pos, self.explosion_images,
100, 300)
global remainingCreeps
remainingCreeps-=1
if remainingCreeps == 0:
print("all dead")
def draw(self):
""" Blit the creep onto the screen that was provided in
the constructor.
"""
if self.state == Creep.ALIVE:
# The creep image is placed at self.pos. To allow for
# smooth movement even when the creep rotates and the
# image size changes, its placement is always
# centered.
#
self.draw_rect = self.image.get_rect().move(
self.pos.x - self.image_w / 2,
self.pos.y - self.image_h / 2)
self.screen.blit(self.image, self.draw_rect)
# The health bar is 15x4 px.
#
health_bar_x = self.pos.x - 7
health_bar_y = self.pos.y - self.image_h / 2 - 6
self.screen.fill( Color('red'),
(health_bar_x, health_bar_y, 15, 4))
self.screen.fill( Color('green'),
( health_bar_x, health_bar_y,
self.health, 4))
elif self.state == Creep.EXPLODING:
self.explode_animation.draw()
elif self.state == Creep.DEAD:
pass
def mouse_click_event(self, pos):
""" The mouse was clicked in pos.
"""
if self._point_is_inside(vec2d(pos)):
self._decrease_health(3)
#begin new player
class Player(pygame.sprite.Sprite):
change_x=0
change_y=0
frame = 0
def __init__(self,x,y):
pygame.sprite.Sprite.__init__(self)
# LOAD PLATER IMAGES
# Set height, width
self.images = []
for i in range(1,17):
img = pygame.image.load("images/player/" + str(i)+".png").convert() #player images
img.set_colorkey(white)
self.images.append(img)
self.image = self.images[0]
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
self.health = 15
self.image_w, self.image_h = self.image.get_size()
health_bar_x = self.rect.x - 7
health_bar_y = self.rect.y - self.image_h / 2 - 6
screen.fill( Color('red'),
(health_bar_x, health_bar_y, 15, 4))
screen.fill( Color('green'),
( health_bar_x, health_bar_y,
self.health, 4))
def changespeed(self,x,y):
self.change_x+=x
self.change_y+=y
def _decrease_health(self, n):
""" Decrease my health by n (or to 0, if it's currently
less than n)
"""
self.health = max(0, self.health - n)
if self.health == 0:
self._explode()
def update(self,walls):
# collision detection
old_x=self.rect.x
new_x=old_x+self.change_x
self.rect.x = new_x
# hit a wall?
collide = pygame.sprite.spritecollide(self, walls, False)
if collide:
# yes
self.rect.x=old_x
old_y=self.rect.y
new_y=old_y+self.change_y
self.rect.y = new_y
collide = pygame.sprite.spritecollide(self, walls, False)
if collide:
# yes
self.rect.y=old_y
# right to left
if self.change_x < 0:
self.frame += 1
if self.frame > 3*4:
self.frame = 0
# Grab the image, divide by 4
# every 4 frames.
self.image = self.images[self.frame//4]
# Move left to right.
# images 4...7 instead of 0...3.
if self.change_x > 0:
self.frame += 1
if self.frame > 3*4:
self.frame = 0
self.image = self.images[self.frame//4+4]
if self.change_y > 0:
self.frame += 1
if self.frame > 3*4:
self.frame = 0
self.image = self.images[self.frame//4+4+4]
if self.change_y < 0:
self.frame += 1
if self.frame > 3*4:
self.frame = 0
self.image = self.images[self.frame//4+4+4+4]
score = 0
# initialize pyGame
pygame.init()
# 800x600 sized screen
global screen
screen = pygame.display.set_mode([800, 600])
screen.fill(black)
#bg_tile_img = pygame.image.load('images/map/grass.png').convert_alpha()
#draw_background(screen, bg_tile_img)
#pygame.display.flip()
# Set title
pygame.display.set_caption('Test')
#background = pygame.Surface(screen.get_size())
#background = background.convert()
#background.fill(black)
# Create the player
player = Player( 50,50 )
player.rect.x=50
player.rect.y=50
movingsprites = pygame.sprite.RenderPlain()
movingsprites.add(player)
# Make the walls. (x_pos, y_pos, width, height)
global wall_list
wall_list=pygame.sprite.RenderPlain()
wall=Wall(0,0,10,600) # left wall
wall_list.add(wall)
wall=Wall(10,0,790,10) # top wall
wall_list.add(wall)
#wall=Wall(10,200,100,10) # poke wall
wall_list.add(wall)
wall=Wall(790,0,10,600) #(x,y,thickness, height)
wall_list.add(wall)
wall=Wall(10,590,790,10) #(x,y,thickness, height)
wall_list.add(wall)
f = open('MapMaker.txt')
num_lines = sum(1 for line in f)
print(num_lines)
lineCount = 0
with open("MapMaker.txt") as infile:
for line in infile:
f = open('MapMaker.txt')
print(line)
coords = line.split(',')
#print(coords[0])
#print(coords[1])
#print(coords[2])
#print(coords[3])
#print(coords[4])
if "tree" in line:
print("tree in")
wall=insertTree(int(coords[0]),int(coords[1]), int(coords[2]),int(coords[3]),coords[4])
wall_list.add(wall)
elif "rock" in line:
print("rock in")
wall=insertRock(int(coords[0]),int(coords[1]), int(coords[2]),int(coords[3]),coords[4] )
wall_list.add(wall)
width = 20
height = 540
height = height - 48
for i in range(0,23):
width = width + 32
name = insertTree(width,540,790,10,"tree")
#wall_list.add(name)
name = insertTree(width,height,690,10,"tree")
#wall_list.add(name)
CREEP_SPAWN_TIME = 200 # frames
creep_spawn = CREEP_SPAWN_TIME
clock = pygame.time.Clock()
bg_tile_img = pygame.image.load('images/map/grass.png').convert()
img_rect = bg_tile_img
FIELD_RECT = Rect(50, 50, 700, 500)
CREEP_FILENAMES = [
'images/player/1.png',
'images/player/1.png',
'images/player/1.png']
N_CREEPS = 3
creep_images = [
pygame.image.load(filename).convert_alpha()
for filename in CREEP_FILENAMES]
explosion_img = pygame.image.load('images/map/tree.png').convert_alpha()
explosion_images = [
explosion_img, pygame.transform.rotate(explosion_img, 90)]
creeps = pygame.sprite.RenderPlain()
done = False
#bg_tile_img = pygame.image.load('images/map/grass.png').convert()
#draw_background(screen, bg_tile_img)
totalCreeps = 0
remainingCreeps = 3
while done == False:
creep_images = pygame.image.load("images/player/1.png").convert()
creep_images.set_colorkey(white)
draw_background(screen, bg_tile_img)
if len(creeps) != N_CREEPS:
if totalCreeps < N_CREEPS:
totalCreeps = totalCreeps + 1
print(totalCreeps)
creeps.add(
Creep( screen=screen,
creep_image=creep_images,
explosion_images=explosion_images,
field=FIELD_RECT,
init_position=( randint(FIELD_RECT.left,
FIELD_RECT.right),
randint(FIELD_RECT.top,
FIELD_RECT.bottom)),
init_direction=(choice([-1, 1]),
choice([-1, 1])),
speed=0.01))
for creep in creeps:
creep.update(60,wall_list)
creep.draw()
for event in pygame.event.get():
if event.type == pygame.QUIT:
done=True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player.changespeed(-2,0)
creep.changespeed(-2,0)
if event.key == pygame.K_RIGHT:
player.changespeed(2,0)
creep.changespeed(2,0)
if event.key == pygame.K_UP:
player.changespeed(0,-2)
creep.changespeed(0,-2)
if event.key == pygame.K_DOWN:
player.changespeed(0,2)
creep.changespeed(0,2)
if event.key == pygame.K_ESCAPE:
pauseGame()
if event.key == pygame.K_1:
global currentEditTool
currentEditTool = "Tree"
changeTool()
if event.key == pygame.K_2:
global currentEditTool
currentEditTool = "Rock"
changeTool()
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.changespeed(2,0)
creep.changespeed(2,0)
if event.key == pygame.K_RIGHT:
player.changespeed(-2,0)
creep.changespeed(-2,0)
if event.key == pygame.K_UP:
player.changespeed(0,2)
creep.changespeed(0,2)
if event.key == pygame.K_DOWN:
player.changespeed(0,-2)
creep.changespeed(0,-2)
if event.type == pygame.MOUSEBUTTONDOWN and pygame.mouse.get_pressed()[0]:
for creep in creeps:
creep.mouse_click_event(pygame.mouse.get_pos())
if editMap == True:
x,y = pygame.mouse.get_pos()
if currentEditTool == "Tree":
name = insertTree(x-10,y-25, 10 , 10, "tree")
wall_list.add(name)
wall_list.draw(screen)
f = open('MapMaker.txt', "a+")
image = pygame.image.load("images/map/tree.png").convert()
screen.blit(image, (30,10))
pygame.display.flip()
f.write(str(x) + "," + str(y) + ",790,10, tree\n")
#f.write("wall=insertTree(" + str(x) + "," + str(y) + ",790,10)\nwall_list.add(wall)\n")
elif currentEditTool == "Rock":
name = insertRock(x-10,y-25, 10 , 10,"rock")
wall_list.add(name)
wall_list.draw(screen)
f = open('MapMaker.txt', "a+")
f.write(str(x) + "," + str(y) + ",790,10,rock\n")
#f.write("wall=insertRock(" + str(x) + "," + str(y) + ",790,10)\nwall_list.add(wall)\n")
else:
None
#pygame.display.flip()
player.update(wall_list)
movingsprites.draw(screen)
wall_list.draw(screen)
pygame.display.flip()
clock.tick(60)
pygame.quit()
Sprite collide is the correct way to do it, you are just handling the return data incorrectly. Basically, sprite collide will no return a boolean of if you are colliding or not with a member of the group. It returns a list of sprites. Basically, it will give you a list of sprites colliding with you in that group. Another thing to watch out for is that the list will also invariably include the sprite itself. After all, it is colliding with itself. Here is a functioning way to test if you are colliding with a wall.
def is_colliding_with_wall(): #this is a function that will determine if you are touching a wall. You have repeated code to test collisions with walls multiple times, so it is best just to have a function
collide = pygame.sprite.spritecollide(self, walls, False) #this gets the list, it is the exact same code as in yours
for collision in collide: #goes through the list, checking each collision
if collision != self: #filters out self collision
return True #if there is a collision that is not self, returns True, that there is a collision with a wall
return False #if it has checked all the collisions and there is only a self collision, then it is not colliding with a wall, so it returns False