How do you move the circle to the mouse position [duplicate] - python

This question already has answers here:
pygame 2 dimensional movement of an enemy towards the player, how to calculate x and y velocity?
(1 answer)
Pygame make sprite walk in given rotation
(1 answer)
How to make smooth movement in pygame
(2 answers)
Closed 1 year ago.
I created a circle in pygame. The circle moves to wherever you click, but instead of "walking" over there, it just appears. I tried some ways, but it doesn't work. If you could find out a way to do it, that would be great. The moving function is in the move function in the Player class.
# import
import pygame
# initialize pygame
pygame.init()
# frame rate variables
FPS = 120
clock = pygame.time.Clock()
# game variables
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 800
mouse_pos = ''
# colors
BLUE = (0, 0, 255)
# activate screen
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption('Bonker')
class Player(pygame.sprite.Sprite):
def __init__(self, x, y):
# init the sprite class
pygame.sprite.Sprite.__init__(self)
self.x = x
self.y = y
self.mouse_x = 0
self.mouse_y = 0
def move(self):
# delta x and delta y
dx = 0
dy = 0
# extract info from tuple
(x, y) = mouse_pos
self.mouse_x = x
self.mouse_y = y
# create tuple destination and current position tuple
destination = (self.mouse_x, self.mouse_y)
current_pos = [self.x, self.y]
# draw the rectangle
if current_pos[0] >= SCREEN_WIDTH // 2:
dx = 10
self.x += dx
if current_pos[0] < SCREEN_WIDTH // 2:
dx = -10
self.x += dx
if current_pos[1] >= SCREEN_HEIGHT // 2:
dy = 10
self.y += dy
if current_pos[1] < SCREEN_HEIGHT // 2:
dy = -10
self.y += dy
pygame.draw.circle(screen, BLUE, (self.x, self.y), 20)
def draw(self):
# draw the circle
pygame.draw.circle(screen, BLUE, (SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2), 20)
# create instances
# player instance
player = Player(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)
player.draw()
# main loop
run = True
while run:
# run frame rate
clock.tick(FPS)
# events
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
screen.fill((0, 0, 0))
mouse_pos = pygame.mouse.get_pos()
player.move()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
run = False
pygame.display.update()
pygame.quit()
I think some code is not needed
Help would be appreciated

This will move the circle to the mouse position. It doesn't move in one diagonal, but that can be changed.
# import
import pygame
# initialize pygame
pygame.init()
# frame rate variables
FPS = 120
clock = pygame.time.Clock()
# game variables
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 800
# colors
BLUE = (0, 0, 255)
# activate screen
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption('Bonker')
class Player(pygame.sprite.Sprite):
def __init__(self, x, y):
# init the sprite class
pygame.sprite.Sprite.__init__(self)
self.rect = pygame.Rect(0, 0, 40, 40)
self.rect.x = x
self.rect.y = y
self.radius = 20
self.destination = None
self.moving = False
self.dx = 0
self.dy = 0
def set_destination(self, pos):
self.destination = pos
# delta x and delta y
self.dx = self.destination[0] - self.rect.centerx
self.dy = self.destination[1] - self.rect.centery
self.moving = True
def move(self):
if self.rect.centerx != self.destination[0]:
if self.dx > 0:
self.rect.centerx += 1
elif self.dx < 0:
self.rect.centerx -= 1
if self.rect.centery != self.destination[1]:
if self.dy > 0:
self.rect.centery += 1
elif self.dy < 0:
self.rect.centery -= 1
elif self.rect.center == self.destination:
self.moving = False
def draw(self):
# draw the circle
pygame.draw.circle(screen, BLUE, self.rect.center, self.radius)
# create instances
# player instance
player = Player(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)
player.draw()
# main loop
run = True
movetime = 100
move = False
while run:
# run frame rate
dt = clock.tick(FPS)
movetime -= dt
if movetime <= 0:
move = True
movetime = 400
# events
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
mouse_pos = pygame.mouse.get_pos()
player.set_destination(mouse_pos)
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
run = False
if player.moving:
player.move()
screen.fill((0, 0, 0))
player.draw()
pygame.display.update()
pygame.quit()

Related

Bullet movement not working as expected when player sprite is moving

My game is a top down shooter. When the player is stationary and is shooting in any direction, the bullet goes in the same direction as the mouse. However, when I move diagonally whilst shooting the bullet is no longer in the direction of the mouse position. So basically it works when the player is stationary, but not when I'm moving.
Edit: I will keep trying to fix this but here is a video to better understand the issue https://imgur.com/a/8QRr1PO
Here is the code:
import pygame
from sys import exit
import math
pygame.init()
# window and text
WIDTH = 1280
HEIGHT = 720
FPS = 60
screen = pygame.display.set_mode((WIDTH,HEIGHT))
pygame.display.set_caption('Shooting problem demo')
game_font = pygame.font.Font('freesansbold.ttf', 50)
clock = pygame.time.Clock()
# loads imgs
background = pygame.image.load("background/gamemap.png").convert()
plain_bg = pygame.image.load("background/plain_bg.png").convert()
bullet_img = pygame.image.load("bullets/bluebullet.png").convert_alpha()
class Player(pygame.sprite.Sprite):
def __init__(self, pos):
super().__init__()
self.image = pygame.image.load("handgun/move/survivor-move_handgun_0.png").convert_alpha()
self.image = pygame.transform.rotozoom(self.image, 0, 0.35)
self.base_player_image = self.image
self.pos = pos
self.base_player_rect = self.base_player_image.get_rect(center = pos)
self.rect = self.base_player_rect.copy()
self.player_speed = 10 # was 4
self.shoot = False
self.shoot_cooldown = 0
def player_turning(self):
self.mouse_coords = pygame.mouse.get_pos()
self.x_change_mouse_player = (self.mouse_coords[0] - (WIDTH // 2))
self.y_change_mouse_player = (self.mouse_coords[1] - (HEIGHT // 2))
self.angle = int(math.degrees(math.atan2(self.y_change_mouse_player, self.x_change_mouse_player)))
self.angle = (self.angle) % 360
self.image = pygame.transform.rotate(self.base_player_image, -self.angle)
self.rect = self.image.get_rect(center=self.base_player_rect.center)
def player_input(self):
self.velocity_x = 0
self.velocity_y = 0
keys = pygame.key.get_pressed()
if keys[pygame.K_w]:
self.velocity_y = -self.player_speed
if keys[pygame.K_s]:
self.velocity_y = self.player_speed
if keys[pygame.K_d]:
self.velocity_x = self.player_speed
if keys[pygame.K_a]:
self.velocity_x = -self.player_speed
if self.velocity_x != 0 and self.velocity_y != 0: # moving diagonally
self.velocity_x /= math.sqrt(2)
self.velocity_y /= math.sqrt(2)
if keys[pygame.K_SPACE]:
self.shoot = True
self.is_shooting()
else:
self.shoot = False
if event.type == pygame.KEYUP:
if event.key == pygame.K_SPACE:
self.shoot = False
def move(self):
self.base_player_rect.centerx += self.velocity_x
self.base_player_rect.centery += self.velocity_y
self.rect.center = self.base_player_rect.center
def is_shooting(self):
if self.shoot_cooldown == 0 and self.shoot:
self.bullet = Bullet(self.base_player_rect.centerx, self.base_player_rect.centery, self.angle)
self.shoot_cooldown = 20
bullet_group.add(self.bullet)
all_sprites_group.add(self.bullet)
def update(self):
self.player_turning()
self.player_input()
self.move()
if self.shoot_cooldown > 0:
self.shoot_cooldown -= 1
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y, angle):
super().__init__()
self.image = bullet_img
self.image = pygame.transform.rotozoom(self.image, 0, 0.1)
self.image.set_colorkey((0,0,0))
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.x = x
self.y = y
self.speed = 10
self.angle = angle
self.x_vel = math.cos(self.angle * (2*math.pi/360)) * self.speed
self.y_vel = math.sin(self.angle * (2*math.pi/360)) * self.speed
self.bullet_lifetime = 750
self.spawn_time = pygame.time.get_ticks()
def bullet_movement(self):
self.x += self.x_vel
self.y += self.y_vel
self.rect.x = int(self.x)
self.rect.y = int(self.y)
if pygame.time.get_ticks() - self.spawn_time > self.bullet_lifetime:
self.kill()
def update(self):
self.bullet_movement()
class Camera(pygame.sprite.Group):
def __init__(self):
super().__init__()
self.offset = pygame.math.Vector2()
self.floor_rect = background.get_rect(topleft = (0,0))
def custom_draw(self):
self.offset.x = player.rect.centerx - (WIDTH // 2)
self.offset.y = player.rect.centery - (HEIGHT // 2)
#draw the floor
floor_offset_pos = self.floor_rect.topleft - self.offset
screen.blit(background, floor_offset_pos)
for sprite in all_sprites_group:
offset_pos = sprite.rect.topleft - self.offset
screen.blit(sprite.image, offset_pos)
# Groups
all_sprites_group = pygame.sprite.Group()
player = Player((900,900))
all_sprites_group.add(player)
bullet_group = pygame.sprite.Group()
camera = Camera()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
screen.blit(plain_bg, (0,0))
camera.custom_draw()
all_sprites_group.update()
pygame.display.update()
clock.tick(FPS)
Actually, there is no problem at all. It is just an optical illusion. The projectile does not move relative to the player, but relative to the camera. The player is always in the center of the screen, because the player doesn't move, but the camera does. When the camera moves, all objects move with the camera.
For example, if you shoot a bullet to the right and move the player up, it will look like the bullet is moving diagonally to the right and down. To the right because it changes position, to the right and down because the player moves upwards.
To illustrate this, I reduced the speed of the player (self.player_speed = 2) and the speed of the bullet (self.speed = 4) and drew the scene on a checkered background:
if event.type == pygame.KEYUP: only makes sens in the event loop, but not in player_input. Shooting only one bullet at once just needs another condition (and not self.shoot):
if keys[pygame.K_SPACE] and not self.shoot:
self.shoot = True
self.is_shooting()
else:
self.shoot = False

It gives me an error that my object has no attribute even though I assigned it [duplicate]

This question already has answers here:
How do I detect collision in pygame?
(5 answers)
Closed 7 months ago.
I'm working in pygame & python and trying to make a zombie shooting game. It all worked smoothly until I tried to add the collision system. If you also know how to add a collision system for this game please leave a comment with a full code.
The error:
type object 'bullet' has no attribute 'rect'
File "C:\Users\*\Desktop\Zombie!\main.py", line 172, in game
collide = pygame.sprite.spritecollide(bullet, enemiesList, False)
File "C:\Users\*\Desktop\Zombie!\main.py", line 44, in menu
game()
File "C:\Users\*\Desktop\Zombie!\main.py", line 211, in <module>
menu()
The code:
import pygame, sys, math, random, time
pygame.init()
#var
screen = pygame.display.set_mode([800, 500])
font = pygame.font.SysFont(None, 20)
playerX = 200
playerY = 200
player = pygame.Rect((playerX, playerY), (10,10))
bullets = pygame.sprite.Group()
clock = pygame.time.Clock()
previous_time = pygame.time.get_ticks()
waveCount = 1
#Remaining enemy count
enemiesList = pygame.sprite.Group()
normalEnemy = 0
speedyEnemy = 0
tankEnemy = 0
def draw_text(text, font, color, surface, x, y):
textobj = font.render(text, 1, color)
textrect = textobj.get_rect()
textrect.topleft = (x, y)
surface.blit(textobj, textrect)
click = False
def menu():
while True:
global click
screen.fill((0,0,0))
draw_text('main menu', font, (255, 255, 255), screen, 20, 20)
mx, my = pygame.mouse.get_pos()
button_1 = pygame.Rect(50, 100, 200, 50)
button_2 = pygame.Rect(50, 200, 200, 50)
if button_1.collidepoint((mx, my)):
if click:
game()
if button_2.collidepoint((mx, my)):
if click:
options()
pygame.draw.rect(screen, (255, 0, 0), button_1)
pygame.draw.rect(screen, (255, 0, 0), button_2)
click = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
click = True
pygame.display.update()
clock.tick(60)
def game():
run = True
class bullet(pygame.sprite.Sprite):
def __init__(self, x, y, mx, my):
pygame.sprite.Sprite.__init__(self)
self.x = x
self.y = y
self.mx = mx
self.my = my
self.speed = 10
self.angle = math.atan2(my-self.y, mx-self.x)
self.x_vel = math.cos(self.angle) * self.speed
self.y_vel = math.sin(self.angle) * self.speed
self.radius = 4
self.mask = pygame.mask.Mask((self.radius, self.radius), True)
self.rect = pygame.Rect(self.x, self.y, self.radius, self.radius)
def update(self):
self.x += int(self.x_vel)
self.y += int(self.y_vel)
pygame.draw.circle(screen, (0, 255, 255), (self.x + 5, self.y + 5), self.radius)
if self.x > 800 or self.x < 0 or self.y > 500 or self.y < 0:
#Remove Bullet Class from list(bullets)
self.kill()
class enemy(pygame.sprite.Sprite):
def __init__(self, enemyType, x, y):
pygame.sprite.Sprite.__init__(self)
self.x = x
self.y = y
if enemyType == "normal":
self.speed = 1
self.hp = 1
self.color = (255, 28, 28)
self.radius = 10
if enemyType == "speedy":
self.speed = 3
self.hp = 1
if enemyType == "tank":
self.speed = 3
self.hp = 3
self.mask = pygame.mask.Mask((self.radius, self.radius), True)
self.rect = pygame.Rect(self.x, self.y, self.radius, self.radius)
def update(self):
global playerX, playerY, enemiesList, bullets
# Find direction vector (dx, dy) between enemy and player.
dx, dy = playerX - self.x, playerY - self.y
dist = math.hypot(dx, dy)
dx, dy = dx / dist, dy / dist # Normalize.
# Move along this normalized vector towards the player at current speed.
self.x += dx * self.speed
self.y += dy * self.speed
pygame.draw.circle(screen, self.color, (self.x, self.y), self.radius)
#Wave system
def waves(waveNumber):
global normalEnemy,speedyEnemy, tankEnemy, enemiesList, waveCount
if waveNumber == 1:
normalEnemy = 5
speedyEnemy = 0
tankEnemy = 0
for i in range(5):
enemiesList.add(enemy("normal", random.randint(0, 800), random.randint(0, 600)))
if waveNumber == 2:
normalEnemy = 7
speedyEnemy = 0
tankEnemy = 0
while run:
clock.tick(60)
screen.fill([255, 255, 255])
mx, my= pygame.mouse.get_pos()
#movements
def movement():
global playerX, playerY, previous_time
key = pygame.key.get_pressed()
mouse = pygame.mouse.get_pressed()
if key[pygame.K_w]:
playerY -= 5
if key[pygame.K_s]:
playerY += 5
if key[pygame.K_d]:
playerX += 5
if key[pygame.K_a]:
playerX -= 5
if mouse[0]:
current_time = pygame.time.get_ticks()
if current_time - previous_time > 500:
previous_time = current_time
bullets.add(bullet(playerX, playerY, mx, my))
for bullets_ in bullets:
bullets_.update()
for enemies_ in enemiesList:
enemies_.update()
if normalEnemy == 0 and speedyEnemy == 0 and tankEnemy == 0:
waves(waveCount)
collide = pygame.sprite.spritecollide(bullet, enemiesList, False)
def draw():
global player, waveCount
player = pygame.Rect((playerX, playerY), (10,10))
pygame.draw.rect(screen, (0, 255, 0), player)
draw_text('wave:' + str(waveCount), font, (0, 0, 0), screen, 20, 20)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
run = False
movement()
draw()
pygame.display.flip()
def options():
running = True
while running:
screen.fill((0,0,0))
draw_text('options', font, (255, 255, 255), screen, 20, 20)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
pygame.display.update()
clock.tick(60)
menu()
I am pretty sure I assigned self.rect at the bullet class, I checked the indents and the spelling but I can't to seem to find the error.
You have a Group bullets and a Group enemiesList. Use pygame.sprite.groupcollide() to detect collisions between Sprites in Groups:
collide = pygame.sprite.groupcollide(bullets, enemiesList, False, False)
Look at the error: type error bullet ... . Somewhere, you're using the bullet class name instead of using an instance of that class.
pygame.sprite.spritecollide - assumes that first parameter is an instance of a class which has 'rect' attribute. But you put the class itself there.
I believe the code must looks like this:
for bullets_ in bullets:
collide = pygame.sprite.spritecollide(bullets_, enemiesList, False)

bullet pawn in pygame

I use pygame and python. I want to make a simple game. Two tanks in scene shoot each other. I have tank class:
class playerObject(pygame.sprite.Sprite):
def __init__(self, rect):
super().__init__()
self.__original_image = pygame.image.load(config.PATH_TO_IMAGES + '\\tank.png').convert_alpha()
self.__original_image = pygame.transform.scale(self.__original_image, (rect.width, rect.height))
self.image = self.__original_image
self.rect = self.image.get_rect()
self.rect.x = rect.x
self.rect.y = rect.y
self.lookAtVector = Vector2(-3, 0)
def addBall(self):
if len(self.balls) < 5:
self.balls.append(ballObject(pygame.Rect(self.rect.centerx, self.rect.top, 10, 10)))
self.balls[-1].lookAtVector.x = self.lookAtVector.x
self.balls[-1].lookAtVector.y = self.lookAtVector.y
angle = 0
__original_image = 0
image = 0
lookAtVector = 0
balls = []
And bullet class:
class ballObject(pygame.sprite.Sprite):
def __init__(self, rect):
super().__init__()
self.image = pygame.image.load(config.PATH_TO_IMAGES + '\\tank.png').convert_alpha()
self.image = pygame.transform.scale(self.image, (5, 5))
self.rect = self.image.get_rect()
self.rect.x = rect.x
self.rect.y = rect.y
self.lookAtVector = Vector2(-3, 0)
lookAtVector = 0
currentSpeed = 1.5
But ball spawns on center of tank. How to do that ball will spawn on tank gun?
tank.png
bullet.png
It needs basic trigonometry.
At start keep distance from center of tank to end of its barrel
self.distance = self.rect.height//2
and later get position of barrel base on angle
def get_barrel_end(self):
rad = math.radians(self.angle)
x = self.rect.centerx - math.sin(rad) * self.distance
y = self.rect.centery - math.cos(rad) * self.distance
return x, y
So you have position for bullet.
I use module math but maybe you could do it with pygame.math
EDIT: The same with pygame.math.Vector2()
At start keep distance from center of tank to end of its barrel
self.distance_vector = pygame.math.Vector2(0, -self.rect.height//2)
and later get position of barrel base on angle
def get_barrel_end(self):
return self.rect.center + self.distance_vector.rotate(-self.angle)
Working example - it draws tank in center and bullet on the end of tank's barrel. Using left/right arrow you can rotate tank and bullet keeps its position on end of tank's barrel.
import pygame
import math
# --- constants ---
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
FPS = 15
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
# --- classes ---
class Tank():
def __init__(self, x, y):
self.image_original = pygame.image.load('tank.png').convert_alpha()
self.angle = 0
self.dirty = False
self.image = self.image_original.copy()
self.rect = self.image.get_rect(center=(x, y))
self.turn_left = False
self.turn_right = False
#self.distance = self.rect.height//2
self.distance_vector = pygame.math.Vector2(0, -self.rect.height//2)
def draw(self, screen):
screen.blit(self.image, self.rect)
def update(self):
if self.turn_left:
self.angle = (self.angle + 2) % 360
self.dirty = True
if self.turn_right:
self.angle = (self.angle - 2) % 360
self.dirty = True
if self.dirty:
self.dirty = False
#print(self.angle)
self.image = pygame.transform.rotate(self.image_original, self.angle)
self.rect = self.image.get_rect(center=self.rect.center)
def handle_event(self, event):
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
self.turn_left = True
elif event.key == pygame.K_RIGHT:
self.turn_right = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
self.turn_left = False
elif event.key == pygame.K_RIGHT:
self.turn_right = False
#def get_barrel_end(self):
# rad = math.radians(self.angle)
# x = self.rect.centerx - math.sin(rad) * self.distance
# y = self.rect.centery - math.cos(rad) * self.distance
# return x, y
def get_barrel_end(self):
return self.rect.center + self.distance_vector.rotate(-self.angle)
class Bullet():
def __init__(self, x, y):
self.image = pygame.image.load('bullet.png').convert_alpha()
self.rect = self.image.get_rect(center=(x, y))
self.dirty = False
def draw(self, screen):
screen.blit(self.image, self.rect)
def update(self, x, y):
self.rect.center = (x, y)
def handle_event(self, event):
pass
# --- main ---
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))#, 32)
screen_rect = screen.get_rect()
tank = Tank(*screen_rect.center)
bullet = Bullet(*tank.get_barrel_end())
clock = pygame.time.Clock()
running = True
while running:
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
tank.handle_event(event)
# - updates -
tank.update()
bullet.update(*tank.get_barrel_end())
# - draws -
screen.fill(WHITE)
tank.draw(screen)
bullet.draw(screen)
pygame.display.flip()
clock.tick(FPS)
pygame.quit()

How do you make the game end when the main player collides with an image (obstacle)?

import math
import random
import pygame
from pygame.locals import *
import sys
def events():
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
pygame.init()
W = 700
H = 400
updater = pygame.time.Clock()
display = pygame.display.set_mode((700, 400))
pygame.display.set_caption("Skating_Game")
x = y = 0
surface = pygame.image.load("man2.png")
pygame.display.set_icon(surface)
class player:
def __init__(self, velocity, maxJumpRange):
self.velocity = velocity
self.maxJumpRange = maxJumpRange
def setLocation(self, x, y):
self.x = x
self.y = y
self.xVelocity = 0
self.jumping = False
self.jumpCounter = 0
self.falling = True
def keys(self):
k = pygame.key.get_pressed()
if k[K_LEFT]:
self.xVelocity = -self.velocity
elif k[K_RIGHT]:
self.xVelocity = self.velocity
else:
self.xVelocity = 0
if k[K_SPACE] and not self.jumping and not self.falling:
self.jumping = True
self.jumpCounter = 0
def move(self):
self.x += self.xVelocity
if self.jumping:
self.y -= self.velocity
self.jumpCounter += 1
if self.jumpCounter == self.maxJumpRange:
self.jumping = False
self.falling = True
elif self.falling:
if self.y <= H - 60 and self.y + self.velocity >= H - 60:
self.y = H - 60
self.falling = False
else:
self.y += self.velocity
def draw(self):
display = pygame.display.get_surface()
character = pygame.image.load("man3.png").convert_alpha()
display.blit(character, (self.x, self.y - 100))
#pygame.draw.circle(display, (255, 255, 255), (self.x, self.y - 25), 25, 0)
def do(self):
self.keys()
self.move()
self.draw()
P = player(3, 50)
P.setLocation(350, 0)
BLACK = ( 0, 0, 0)
g=0
font = pygame.font.SysFont("Plump", 30)
obstacle = pygame.image.load("obstacle.png").convert_alpha()
background = pygame.image.load("Road.png").convert()
x = 0
while True:
events()
rel_x = x % background.get_rect().width
display.blit(background, (rel_x - background.get_rect().width,0))
if rel_x < 700:
display.blit(background, (rel_x, 0))
x -= 1
g += 0.01
pygame.draw.rect(display, (255,255,255,128), [rel_x, 275, 150, 50])
display.blit(obstacle, (rel_x, 250))
text = font.render("Score: "+str(int(g)), True, (255, 255, 255))
display.blit(text, (0,0))
P.do()
if P.rect.collidepoint(self.x,self.y):
pygame.quit()
pygame.display.update()
updater.tick(200)
So if the player collides with the obstacle image the game should stop. How do i do this? I have made a class for the player and the obstacle is just an image which is constantly moving.
I was thinking maybe I could track the x and y coordinate of the player and obstacle and when their radius overlaps the game could stop.
Here's a working (simplified) version of your program with some comments. You have to create rects for the obstacle and the player and then check if the rects collide with the help of the colliderect method.
import sys
import pygame
from pygame.locals import *
pygame.init()
W = 700
H = 400
updater = pygame.time.Clock()
display = pygame.display.set_mode((700, 400))
PLAYER_IMAGE = pygame.Surface((30, 50))
PLAYER_IMAGE.fill(pygame.Color('dodgerblue1'))
class Player:
def __init__(self, x, y, velocity, maxJumpRange):
self.velocity = velocity
self.maxJumpRange = maxJumpRange
self.image = PLAYER_IMAGE # Give the player an image.
# Create a rect with the size of the PLAYER_IMAGE and
# pass the x, y coords as the topleft argument.
self.rect = self.image.get_rect(topleft=(x, y))
self.x = x
self.y = y
self.xVelocity = 0
self.jumping = False
self.jumpCounter = 0
self.falling = True
def keys(self):
k = pygame.key.get_pressed()
if k[K_LEFT]:
self.xVelocity = -self.velocity
elif k[K_RIGHT]:
self.xVelocity = self.velocity
else:
self.xVelocity = 0
if k[K_SPACE] and not self.jumping and not self.falling:
self.jumping = True
self.jumpCounter = 0
def move(self):
self.x += self.xVelocity
if self.jumping:
self.y -= self.velocity
self.jumpCounter += 1
if self.jumpCounter == self.maxJumpRange:
self.jumping = False
self.falling = True
elif self.falling:
if self.y >= H - 160: # Simplified a little.
self.y = H - 160
self.falling = False
else:
self.y += self.velocity
# Update the position of the rect, because it's
# used for the collision detection.
self.rect.topleft = self.x, self.y
def draw(self, display):
# Just draw the image here.
display.blit(self.image, (self.x, self.y))
def do(self):
self.keys()
self.move()
player = Player(350, 0, 3, 50)
obstacle = pygame.Surface((150, 50))
obstacle.fill(pygame.Color('sienna1'))
# Create a rect with the size of the obstacle image.
obstacle_rect = obstacle.get_rect()
g = 0
x = 0
FPS = 60 # Cap the frame rate at 60 or 30 fps. 300 is crazy.
while True:
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
# --- Update the game ---
player.do()
rel_x = x % display.get_width()
x -= 7
g += 0.01
obstacle_rect.topleft = rel_x, 250 # Update the position of the rect.
# --- Draw everything ---
display.fill((30, 30, 30))
display.blit(obstacle, (rel_x, 250))
if g > 30:
display.blit(obstacle, (rel_x+350, 250))
# Check if the obstacle rect and the player's rect collide.
if obstacle_rect.colliderect(player.rect):
print("Game over!") # And call pygame.quit and sys.exit if you want.
# Draw the image/surface of the player onto the screen.
player.draw(display)
# Draw the actual rects of the objects (for debugging).
pygame.draw.rect(display, (200, 200, 0), player.rect, 2)
pygame.draw.rect(display, (200, 200, 0), obstacle_rect, 2)
pygame.display.update()
updater.tick(FPS)
Pygame rectangles include a collidepoint and colliderect method that allows you to check to see if something intersects with a rectangle. So you could have rectangles drawn beneath the obstacle and check to see if the player's coordinates intersect with the rectangle. Like this:
if self.rect.collidepoint(self.x,self.y):
pygame.quit()

Sprite Health in Pygame [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
I'm making a very basic game, and I'm trying to make it so that the bird(player) dodges the rocks and if the bird is hit by the rocks it dies. But I can't figure out how to make the game know if the duck got hit by the rock.
Here is my code:
import os, sys
import random
import time
img_path = os.path.join('C:\Python27', 'player.png')
img_path2 = os.path.join('C:\Python27', 'rock.png')
class Bird(object):
def __init__(self):
self.image = pygame.image.load(img_path)
self.x = 0
self.y = 0
def handle_keys(self):
key = pygame.key.get_pressed()
dist = 2
if key[pygame.K_DOWN]:
self.y += dist
elif key[pygame.K_UP]:
self.y -= dist
if key[pygame.K_RIGHT]:
self.x += dist
elif key[pygame.K_LEFT]:
self.x -= dist
def draw(self, surface):
surface.blit(self.image, (self.x, self.y))
def bird_health(self):
health = 1
if health ==0:
sys.exit()
def background(self, surface):
bg = os.path.join('C:\Python27', 'bg.png')
self.image2 = pygame.image.load(bg)
surface.blit(self.image2, (0,0))
class Rock(object):
def __init__(self, x=640, y=0,):
self.image = pygame.image.load(img_path2)
self.x = x
self.y = y
dist = 10
self.dist = dist
def rock(self):
dist = 10
self.x -=dist
def rock_draw(self, surface):
surface.blit(self.image, (self.x, self.y))
pygame.init()
screen = pygame.display.set_mode((640, 200))
bird = Bird() # create an instance
rock = Rock()
clock = pygame.time.Clock()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit() # quit the screen
running = False
if rock.x < 0:
y = random.randint(10, 190)
rock = Rock(640, y)
bird.handle_keys()
rock.rock()
screen.fill((255,255,255))
bird.background(screen)
bird.draw(screen)
rock.rock_draw(screen)
pygame.display.update()
clock.tick(40)
For now I just want it to exit if the bird's health = 0.
I haven't done pygame in a while, but reference this:
http://www.pygame.org/docs/ref/sprite.html#pygame.sprite.spritecollideany
Pygame has a built in collide function, spritecollideany()
or you can use this:
def checkCollision(bird, rock):
if bird.x == rock.x and bird.y == rock.y:
sys.exit()
and in the bird and rock classes, make sure the x and y are accessible. This will only work if the bird's corner is equal to the rock's corner, but you can add clauses to check. For example:
if bird.x == rock.x and bird.y == rock.y or bird.x == rock.x + rock.length and...
This will be expanded upon based on where the bird is centered.
Here is a program where I detect if the ball hits the paddle in, hope it helps. all the way at the bottom (in a seperate code box thing) is just the code where i detect if they collide.
import pygame
# Constants
WIDTH = 700
HEIGHT = 500
SCREEN_AREA = pygame.Rect(0, 0, WIDTH, HEIGHT)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
# Initialization
pygame.init()
screen = pygame.display.set_mode([WIDTH, HEIGHT])
pygame.mouse.set_visible(0)
pygame.display.set_caption("Breakout Recreation WIP")
clock = pygame.time.Clock()
# Variables
paddle = pygame.Rect(350, 480, 50, 10)
ball = pygame.Rect(10, 250, 15, 15)
paddle_movement_x = 0
ball_direction = (1, 1)
balls = 3
done = False
while not done and balls > 0:
# Process events
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
paddle_movement_x = -2
elif keys[pygame.K_RIGHT]:
paddle_movement_x = 2
else:
paddle_movement_x = 0
# Move paddle
paddle.move_ip(paddle_movement_x, 0)
paddle.clamp_ip(SCREEN_AREA)
# Move ball
ball.move_ip(*ball_direction)
if ball.right > WIDTH or ball.left < 0:
ball_direction = -ball_direction[0], ball_direction[1]
elif ball.top < 0 or paddle.colliderect(ball):
ball_direction = ball_direction[0], -ball_direction[1]
elif ball.bottom > HEIGHT:
balls = balls - 1
ball_direction = (1, 1)
ball = pygame.Rect(10, 250, 15, 15)
ball.clamp_ip(SCREEN_AREA)
# Redraw screen
screen.fill(BLACK)
pygame.draw.rect(screen, WHITE, paddle)
pygame.draw.rect(screen, WHITE, ball)
pygame.display.flip()
clock.tick(100)
pygame.quit()
here is the code where i basically change the ball's direction:
# Move ball
ball.move_ip(*ball_direction)
if ball.right > WIDTH or ball.left < 0:
ball_direction = -ball_direction[0], ball_direction[1]
elif ball.top < 0 or paddle.colliderect(ball):
ball_direction = ball_direction[0], -ball_direction[1]
elif ball.bottom > HEIGHT:
balls = balls - 1
ball_direction = (1, 1)
ball = pygame.Rect(10, 250, 15, 15)

Categories

Resources