This question already has answers here:
How to implement barriers to stop the player moving through walls
(1 answer)
Collision for Pygame Game Map
(2 answers)
Adding collision to maze walls
(1 answer)
How do I prevent the player from moving through the walls in a maze?
(3 answers)
Closed 7 months ago.
I'm trying to make a maze platformer game in pygame, but my player keeps jumping through the floor. I didn't find any good answers or tutorials to that problem. I hope to get an answer from here soon. I didn't add the player code, because StackOverflow thought my question was mostly code and the movements are not made by the player sprite, either. My previous question got deleted, but the "similar question" did not solve my problem at all. Here's my code...
Main code:
import pygame
from levels import Level
from misc import Background
from player import Player
from pygame.locals import (
RLEACCEL,
K_UP,
K_DOWN,
K_LEFT,
K_RIGHT,
K_ESCAPE,
KEYDOWN,
QUIT,
)
screen = pygame.display.set_mode((800,600))
clock = pygame.time.Clock()
player = Player()
background = pygame.Surface(screen.get_size())
bg = Background()
level = Level()
running = True
while running:
screen.blit(background, (0, 0))
bg.walling()
pressed_keys = pygame.key.get_pressed()
level.render()
level.move(pressed_keys)
player.update(pressed_keys)
screen.blit(player.surf, player.rect)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
pygame.display.flip()
clock.tick(100)
pygame.quit()
Map code:
import pygame
from pygame.locals import (
RLEACCEL,
K_UP,
K_DOWN,
K_LEFT,
K_RIGHT,
K_ESCAPE,
KEYDOWN,
QUIT,
)
from player import Player
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
player = Player()
class Level(pygame.sprite.Sprite):
def __init__(self):
super(Level, self).__init__()
self.level = 0
self.map1 = pygame.image.load("../misc/maps/level1.png").convert_alpha()
self.map1 = pygame.transform.scale(self.map1, (4000, 3000))
self.surf = pygame.Surface((4000, 3000))
self.rect = self.surf.get_rect(center=(500,1700))
self.map = self.map1
self.jumping = False
self.v = 10
self.m = 1
def render(self):
screen.blit(self.map, self.rect)
self.floorcolor = screen.get_at((400,402))
self.leftcolor = screen.get_at((380, 372))
self.rightcolor = screen.get_at((420,372))
self.upcolor = screen.get_at((400, 342))
def jump(self):
if self.jumping == False:
self.jumping = True
if self.jumping:
F = (1 / 2) * self.m * (self.v ** 2)
self.rect.move_ip(0,F)
self.v = self.v - 1
if self.v < 0:
self.m = -1
if self.v == -9:
self.jumping = False
self.v = 10
self.m = 1
def move(self, pressed_keys):
if pressed_keys[K_UP]:
self.jump()
if self.floorcolor != (88,88,88) and self.floorcolor != (64,64,64):
self.rect.move_ip(0, -4)
if self.leftcolor == (88,88,88) or self.leftcolor == (64,64,64):
self.rect.move_ip(-4,0)
if self.rightcolor == (88,88,88) or self.rightcolor == (64,64,64):
self.rect.move_ip(4,0)
if self.upcolor == (88,88,88) or self.upcolor == (64,64,64):
self.rect.move_ip(0,-4)
if pressed_keys[K_LEFT]:
self.rect.move_ip(4, 0)
if pressed_keys[K_RIGHT]:
self.rect.move_ip(-4, 0)
Related
This question already has an answer here:
Why is my collision test always returning 'true' and why is the position of the rectangle of the image always wrong (0, 0)?
(1 answer)
Closed 1 year ago.
I read an article about how a mouse cursor can detect a rect, and it includes the line ".get_rect()" but somehow it doesnt work
heres the articles code ->
import pygame
pygame.init()
width=350;
height=400
screen = pygame.display.set_mode( (width, height ) )
pygame.display.set_caption('clicked on image')
redSquare = pygame.image.load("images/red-square.png").convert()
x = 20; # x coordnate of image
y = 30; # y coordinate of image
screen.blit(redSquare , ( x,y)) # paint to screen
pygame.display.flip() # paint screen one time
running = True
while (running):
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
# Set the x, y postions of the mouse click
x, y = event.pos
if redSquare.get_rect().collidepoint(x, y):
print('clicked on image')
#loop over, quite pygame
pygame.quit()
heres my code ->
import pygame
import os
import sys
pygame.init()
width,height = (1100,800)
WIN = pygame.display.set_mode((width,height))
global bcard
bg_filename = os.path.join('C:\\Users\\USER\\Desktop\\Python\\picture match','background.jpg')
bg = pygame.image.load(bg_filename)
bg = pygame.transform.scale(bg, (width, height)).convert()
card_width=130
card_height=160
blue_card=pygame.image.load(os.path.join('C:\\Users\\USER\\Desktop\\Python\\picture match','blue_card.png'))
red_card=pygame.image.load(os.path.join('C:\\Users\\USER\\Desktop\\Python\\picture match','red_card.png'))
bcard=pygame.transform.scale(blue_card,(card_width,card_height)).convert()
rcard=pygame.transform.scale(red_card,(card_width,card_height)).convert()
text=pygame.image.load(os.path.join('C:\\Users\\USER\\Desktop\\Python\\picture match','text.png'))
global clicking
clicking = False
def pictures():
global card1
card1=WIN.blit(bcard,(30,200))
card2=WIN.blit(rcard,(200,200))
card3=WIN.blit(bcard,(370,200))
card4=WIN.blit(rcard,(550,200))
card5=WIN.blit(bcard,(730,200))
card6=WIN.blit(rcard,(900,200))
card7=WIN.blit(rcard,(30,400))
card8=WIN.blit(bcard,(200,400))
card9=WIN.blit(rcard,(370,400))
card10=WIN.blit(bcard,(550,400))
card11=WIN.blit(rcard,(730,400))
card12=WIN.blit(bcard,(900,400))
card13=WIN.blit(bcard,(30,600))
card14=WIN.blit(rcard,(200,600))
card15=WIN.blit(bcard,(370,600))
card16=WIN.blit(rcard,(550,600))
card17=WIN.blit(bcard,(730,600))
card18=WIN.blit(rcard,(900,600))
card1_rect=pygame.Rect(30,200,130,160)
card1_rect=pygame.Rect(200,200,130,160)
card1_rect=pygame.Rect(370,200,130,160)
card1_rect=pygame.Rect(550,200,130,160)
card1_rect=pygame.Rect(730,200,130,160)
card1_rect=pygame.Rect(900,200,130,160)
WIN.blit(text,(25,0))
def draw():
WIN.blit(bg,(0,0))
pictures()
def main():
global clicking
global card1
global bcard
run = True
mx , my = pygame.mouse.get_pos()
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
if bcard.get_rect().collidepoint(mx, my):
print('clicked on image')
draw()
pygame.display.flip()
main()
its suppose to be a picture match game btw, heres the error code "AttributeError: 'pygame.Surface' object has no attribute 'get_rect'"
pygame.Surface.get_rect.get_rect() returns a rectangle with the size of the Surface object, that always starts at (0, 0) since a Surface object has no position. A Surface is blit at a position on the screen. The position of the rectangle can be specified by a keyword argument. For example, the top left of the rectangle can be specified with the keyword argument topleft:
if bcard.get_rect().collidepoint(mx, my):
if bcard.get_rect(topleft = (30, 200)).collidepoint(mx, my):
print('clicked on image')
This question already has answers here:
Add scrolling to a platformer in pygame
(4 answers)
Closed last month.
I am using pygame framework to implement my game in Python. Below is my code.
I do not know how to properly ask questions at StackOverflow, so I have included the whole program so that you can see all the details.
I would like to have a camera that would follow my player, but I do not know how to do that.
Could you, please, help me?
import pygame
pygame.init()
class Oyun():
def __init__(self):
self.x = 20
pygame.display.set_caption("Cabbar_Oyunda_Vol01")
self.uzunluk = 1280
self.genişlik = 800
self.pencere = pygame.display.set_mode((self.uzunluk, self.genişlik))
self.area = self.uzunluk * self.genişlik
self.clock = pygame.time.Clock()
self.adam = pygame.image.load("R8E.png")
self.bg = pygame.image.load("mountains.png").convert()
self.bgWidth, self.bgHeight = self.bg.get_rect().size
self.stageWidth = self.bgWidth * 2
self.stagePosX=0
self.startScrollingPosX=self.uzunluk/2
self.circleRadius=25
self.circlePosX=self.circleRadius
self.playerPosX = self.circleRadius
self.playerPosY = 685
self.playerVelocityX = 0
self.right = False
self.left = False
self.walkLeft = [pygame.image.load('L1.png'), pygame.image.load('L2.png'), pygame.image.load("L3.png"), pygame.image.load('L4.png'), pygame.image.load('L5.png'), pygame.image.load('L6.png'), pygame.image.load('L7.png'), pygame.image.load('L8.png'), pygame.image.load('L9.png')]
self.walkRight = [pygame.image.load('R1.png'), pygame.image.load('R2.png'), pygame.image.load('R3.png'), pygame.image.load('R4.png'), pygame.image.load('R5.png'), pygame.image.load('R6.png'), pygame.image.load('R7.png'), pygame.image.load('R8.png'),pygame.image.load('R9.png')]
self.walkCount=0
self.canavar_left=[pygame.image.load("L1E.png"),pygame.image.load("L2E.png"),pygame.image.load("L3E.png"),pygame.image.load("L4E.png"),pygame.image.load("L5E.png"),pygame.image.load("L6E.png"),pygame.image.load("L7E.png"),pygame.image.load("L8E.png"),pygame.image.load("L9E.png")]
self.canavar_right = [pygame.image.load("R1E.png"), pygame.image.load("R2E.png"), pygame.image.load("R3E.png"),pygame.image.load("R4E.png"), pygame.image.load("R5E.png"), pygame.image.load("R6E.png"),pygame.image.load("R7E.png"), pygame.image.load("R8E.png"), pygame.image.load("R9E.png")]
self.c_walkount=0
self.isJump = False
self.jumpCount = 10
self.sayac=0
self.yorgunluk_x=70
self.font=pygame.font.SysFont("Arial",17)
self.mermi=pygame.image.load("bullet.png")
self.mermi_x=0
self.mermi_y=0
self.mermi_stage="ready"
self.deneme=pygame.image.load("bg.jpg")
self.a = self.stagePosX + 1300
self.canavar=False
pygame.mixer.music.load("background.wav")
pygame.mixer.music.play(-1)
self.yon=1
self.scroll=[0,0]
def move(self):
self.clock.tick(40)
if self.walkCount + 1 >= 27:
self.walkCount = 0
if self.right:
self.pencere.blit(self.walkRight[self.walkCount // 3], (self.circlePosX, self.playerPosY))
self.walkCount += 1
elif self.left:
self.pencere.blit(self.walkLeft[self.walkCount // 3], (self.circlePosX, self.playerPosY))
self.walkCount += 1
else:
self.pencere.blit(self.walkRight[0], (self.circlePosX, self.playerPosY))
if self.canavar:
if self.a>1400 or self.a<1200:
self.yon*=-1
self.a += 2 * self.yon
def fire_bullet(self,circlePosX,playerPosY):
self.mermi_stage="fire"
self.pencere.blit(self.mermi,(circlePosX+40,playerPosY+20))
def kontrol(self):
keys=pygame.key.get_pressed()
if keys[pygame.K_SPACE]:
if self.mermi_stage is "ready":
self.mermi_x=self.circlePosX
self.mermi_y=self.playerPosY
self.fire_bullet(self.mermi_x,self.mermi_y)
self.mermi_ses = pygame.mixer.Sound("laser.wav")
self.mermi_ses.play()
if self.mermi_stage is "fire":
self.fire_bullet(self.mermi_x,self.mermi_y)
self.mermi_x+=18
if self.mermi_x>=1280:
self.mermi_x=self.circlePosX
self.mermi_stage="ready"
self.pencere.blit(self.adam, (self.a, 685))
def Game(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
return "son"
self.pencere.blit(self.bg, (0, 0))
keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT]:
self.left = False
self.right = True
self.circlePosX += 5
elif keys[pygame.K_LEFT]:
self.left = True
self.right = False
self.circlePosX=-5
if not (self.isJump):
if keys[pygame.K_UP]:
self.isJump = True
self.left = False
self.right = True
self.walkCount = 0
self.sayac += 1
else:
if self.jumpCount >= -10:
self.playerPosY -= (self.jumpCount * abs(self.jumpCount)) * 0.5
self.jumpCount -= 1
else:
self.jumpCount = 10
self.isJump = False
self.canavar=True
self.move()
self.kontrol()
pygame.display.update()
Game = Oyun()
while True:
Durum = Game.Game()
if Durum == "son":
break
A simple(but not most efficient) way to do this would be to move the background and all other assets, while keeping the player stationary.
# insert code in each object in background/assets
if right:
OBJECT.right() # code to change location
if left:
OBJECT.left() #code to change location
Also, off-topic, but it is easier to have a single direction variable with -1 for left, 0 for stationary, and 1 for right. You can also easily add speed to this, too, so keep this in mind and implement it if you can.
I have this game where a balloon needs to explode every 3 seconds, but the explosion needs to be delayed for about 1 second (right now, it's almost immediate). I have the balloon every 3 seconds part down, but I'm having trouble on the delay part. If I use sleep or wait, all the other animations I have going on stop, and that's not what I want. Does anyone have any tips?
Here's a complete example. I highly recommend using object-oriented programming, pygame sprites and sprite groups. These sprites have a timer attribute which is decreased by the delta time, dt, each frame. When the time of a balloon is up, it is removed from the containing sprite groups balloon.kill() and an explosion instance is added instead. The explosion also has a timer and removes itself, self.kill(), when the timer is below 0. (Press a mouse button to add more balloons.)
import pygame as pg
pg.init()
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
# Images. Balloon = blue, explosion = orange.
BALLOON_IMAGE = pg.Surface((50, 50), pg.SRCALPHA)
pg.draw.circle(BALLOON_IMAGE, pg.Color('steelblue2'), (25, 25), 25)
EXPLOSION_IMAGE = pg.Surface((80, 80), pg.SRCALPHA)
pg.draw.circle(EXPLOSION_IMAGE, pg.Color('sienna1'), (40, 40), 40)
class Balloon(pg.sprite.Sprite):
def __init__(self, pos):
super().__init__()
self.image = BALLOON_IMAGE
self.rect = self.image.get_rect(center=pos)
self.timer = 3
def update(self, dt):
self.timer -= dt
class Explosion(pg.sprite.Sprite):
def __init__(self, pos):
super().__init__()
self.image = EXPLOSION_IMAGE
self.rect = self.image.get_rect(center=pos)
self.timer = 1
def update(self, dt):
self.timer -= dt
if self.timer <= 0:
self.kill()
balloons = pg.sprite.Group(Balloon((300, 300)))
all_sprites = pg.sprite.Group(balloons)
done = False
while not done:
dt = clock.tick(30) / 1000
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
elif event.type == pg.MOUSEBUTTONDOWN:
balloon = Balloon(event.pos)
balloons.add(balloon)
all_sprites.add(balloon)
all_sprites.update(dt)
for balloon in balloons:
if balloon.timer <= 0:
balloon.kill()
all_sprites.add(Explosion(balloon.rect.center))
screen.fill((30, 30, 30))
all_sprites.draw(screen)
pg.display.flip()
pygame.time.get_ticks() gives current time in milliseconds.
You can set (3s = 3000ms)
next_baloon = pygame.time.get_ticks() + 3*1000
and in every loop you have to check if it is time to start ballon
if next_baloon <= pygame.time.get_ticks():
start_ballon()
next_baloon = pygame.time.get_ticks() + 3*1000
next_explosion = pygame.time.get_ticks() + 1*1000
if next_explosion <= pygame.time.get_ticks():
explode_ballon()
I have a problem I'm stuck now for last two days. In file game_function in nested loop I'm creating aliens, when I added randint to create random numbers of aliens in a row I run in to problem. Not always (just re-run the game) but sometimes when I detect sprite edge as a method of Alien class Aliens/sprites won't change the direction, follow x axis to the right and constantly dropping down Aliens each pass of check edge. I don't know what the heck is that. Before when I haven't been using randit to generate random numbers of aliens in a row, everything was just fine.
settings.py
class Settings():
"""A class to store all settings for Alien Invasion"""
def __init__(self):
"""Initialize the game settings"""
#Screen settings
self.screen_width = 1200
self.screen_height = 800
self.bg_color = (230,230,230)
#ship settings
self.ship_speed_factor = 1.5
#Bullet settings
self.bullet_speed_factor = 1
self.bullet_width = 3
self.bullet_height = 15
self.bullet_color = (60, 60, 60)
self.bullets_allowed = 3
# Alien settings
self.alien_speed_factor = 1
self.fleet_drop_speed = 10
# fleet_direction of 1 represents right; -1 represents left.
self.fleet_direction = 1
ship.py
import pygame
class Ship():
def __init__(self,ai_settings, screen):
"""Initialize the ship and sets the starting position."""
self.screen = screen
self.ai_settings = ai_settings
#load the ship image and get its rect
self.image = pygame.image.load('images/ship.png')
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()
# Start each new ship at the bottom center of the screen
self.rect.centerx = self.screen_rect.centerx
self.rect.bottom = self.screen_rect.bottom
self.center = float(self.rect.centerx)
#Movement Flag
self.moving_right = False
self.moving_left = False
def update(self):
"""Update the ship's position based on the movement Flag."""
#Update the ship's center value, not the rect
if self.moving_right and self.rect.right < self.screen_rect.right:
self.center += self.ai_settings.ship_speed_factor
if self.moving_left and self.rect.left > 0:
self.center -= self.ai_settings.ship_speed_factor
#update rect object from self.center
self.rect.centerx = self.center
def blitme(self):
"""Draw the ship at its current location"""
self.screen.blit(self.image, self.rect)
In a function create_fleet(ai_settings, screen, ship, aliens) is nested loop, when instead of generating random number between 3-9 and then placing new instance in row I've used constant calculation which always gives 9 aliens in row everything runned just fine. Aliens changed everytime directions and just one time dropped down until next check_edge event passed the condition. So from one wall to another. Now when the randint is in place, NOT ALWAYS, when check_edge method confirms true, then call to function change_fleet_direction() is made and there I see problem, it just sometimes doesn't change the direction. where for direction is used just simple +1 or -1 and in calling for update in Alien class it should either decrease x axis or increase until edge event.
game_functions.py
import sys
import pygame
from bullet import Bullet
from alien import Alien
from random import randint
def create_fleet(ai_settings, screen, ship, aliens):
"""Create a full fleet of aliens."""
#Create an Alien and find the number of aliens in a row
name= 'First unused'
alien = Alien(ai_settings, screen,name)
number_aliens_x = get_number_aliens_x(ai_settings, alien.rect.width)
number_rows = get_number_rows(ai_settings, ship.rect.height,
alien.rect.height)
# Create the fleet of aliens.
for row_number in range(number_rows):
random_num = randint(3, number_aliens_x)
for alien_number in range(0, random_num):
create_alien(ai_settings, screen, aliens, alien_number,
row_number)
def get_number_aliens_x(ai_settings, alien_width):
"""Determine the number of aliens that fit in a row."""
available_space_x = ai_settings.screen_width - 2 * alien_width
number_aliens_x = int(available_space_x / (2 * alien_width))
return number_aliens_x
def get_number_rows(ai_settings, ship_height, alien_height):
"""Determine the number of rows of aliens that fit on the screen."""
available_space_y = (ai_settings.screen_height -
(3 * alien_height) - ship_height)
number_rows = int(available_space_y / (2 * alien_height))
return number_rows
def create_alien(ai_settings, screen, aliens, alien_number, row_number):
"""Create alien and place it in the row"""
name = "Alien number " + str(alien_number) + " in row " + str(row_number)
alien = Alien(ai_settings, screen, name)
alien_width = alien.rect.width
alien.x = alien_width + 2 * alien_width * alien_number
alien.rect.x = alien.x
alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
aliens.add(alien)
def check_keydown_events(event, ai_settings, screen, ship, bullets):
"""Respond to key presses"""
if event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.key == pygame.K_LEFT:
ship.moving_left = True
elif event.key == pygame.K_SPACE:
fire_bullet(ai_settings, screen, ship, bullets)
elif event.key == pygame.K_q:
sys.exit()
def fire_bullet(ai_settings, screen, ship, bullets):
# Create a new bullet and add it to the bullets group.
if len(bullets) < ai_settings.bullets_allowed:
new_bullet = Bullet(ai_settings, screen, ship)
bullets.add(new_bullet)
def check_keyup_events(event,ship):
"""Respond to key releases"""
if event.key == pygame.K_RIGHT:
ship.moving_right = False
elif event.key == pygame.K_LEFT:
ship.moving_left = False
def check_events(ai_settings, screen, ship, bullets):
"""Respond to keypress and mouse events"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
check_keydown_events(event, ai_settings, screen, ship, bullets)
elif event.type == pygame.KEYUP:
check_keyup_events(event, ship)
def update_screen(ai_settings, screen, ship, aliens, bullets):
"""Update images on the screen and flip to the new screen."""
# Redraw the screen during each pass through the loop.
screen.fill(ai_settings.bg_color)
# Redraw all bullets behind ship and aliens.
for bullet in bullets.sprites():
bullet.draw_bullet()
ship.blitme()
aliens.draw(screen)
# Make the most recently drawn screen visible.
pygame.display.flip()
def update_bullets(bullets):
"""Update position of bullets and get rid of old bullets."""
# Update bullet positions.
bullets.update()
# Get rid of bullets that have disappeared.
for bullet in bullets.copy():
if bullet.rect.bottom <= 0:
bullets.remove(bullet)
def check_fleet_edges(ai_settings, aliens):
"""Respond appropriately if any aliens have reached an edge."""
for alien in aliens.sprites():
if alien.check_edges():
print(alien.name)
change_fleet_direction(ai_settings, aliens)
break
def change_fleet_direction(ai_settings, aliens):
"""Drop the entire fleet and change the fleet's direction."""
print("old direction " + str(ai_settings.fleet_direction))
for alien in aliens.sprites():
alien.rect.y += ai_settings.fleet_drop_speed
if ai_settings.fleet_direction == 1:
ai_settings.fleet_direction = -1
else:
ai_settings.fleet_direction = 1
print("new direction" + str(ai_settings.fleet_direction))
def update_aliens(ai_settings, aliens):
"""
Check if the fleet is at an edge,
and then update the positions of all aliens in the fleet.
"""
check_fleet_edges(ai_settings, aliens)
aliens.update()
Main file alien_invasion.py
import pygame
from pygame.sprite import Group
from settings import Settings
from ship import Ship
import game_functions as gf
def run_game():
# Initialize game and create a screen object.
pygame.init()
ai_settings = Settings()
screen = pygame.display.set_mode(
(ai_settings.screen_width, ai_settings.screen_height))
pygame.display.set_caption("Alien Invasion")
ship = Ship(ai_settings,screen)
#Make a group to store bullets in
bullets = Group()
aliens = Group()
#Create the fleet of aliens
gf.create_fleet(ai_settings, screen, ship, aliens)
# Start the main loop for the game.
while True:
gf.check_events(ai_settings, screen, ship, bullets)
ship.update()
bullets.update()
gf.update_bullets(bullets)
gf.update_aliens(ai_settings, aliens)
gf.update_screen(ai_settings, screen, ship, aliens, bullets)
run_game()
bullet.py
import pygame
from pygame.sprite import Sprite
class Bullet(Sprite):
"""A class to manage bullets fired from the ship"""
def __init__(self, ai_settings, screen, ship):
"""create a bullet object at the ship's current position"""
super().__init__()
self.screen = screen
#Create a bullet rect at (0, 0) and then set correct position
self.rect = pygame.Rect(0, 0, ai_settings.bullet_width,
ai_settings.bullet_height)
self.rect.centerx = ship.rect.centerx
self.rect.top = ship.rect.top
#Store the bullet position as a decimal value.
self.y = float(self.rect.y)
self.color = ai_settings.bullet_color
self.speed_factor = ai_settings.bullet_speed_factor
def update(self):
"""Move bullet up the scereen"""
#Update the decimal position of the bullet
self.y -= self.speed_factor
#Update the rect position
self.rect.y = self.y
def draw_bullet(self):
"""Draw the bullet to the screen"""
pygame.draw.rect(self.screen, self.color, self.rect)
alien.py
import pygame
from pygame.sprite import Sprite
class Alien(Sprite):
"""A class to represent a single alien in the fleet"""
def __init__(self, ai_settings, screen, name):
"""Initialize the alien and set its starting position"""
super().__init__()
self.screen = screen
self.ai_settings = ai_settings
#Load the alien image and set its rect attribute.
self.image = pygame.image.load('images/alien.bmp')
self.rect = self.image.get_rect()
#Start each alien near the top left of the screen
self.rect.x = self.rect.width
self.rect.y = self.rect.height
#Store the alien's exact position
self.x = float(self.rect.x)
self.name = name
# def blitme(self):
# """Draw the alien at its current location."""
# self.screen.blit(self.image, self.rect)
#
def check_edges(self):
"""Return True if alien is at edge of screen."""
screen_rect = self.screen.get_rect()
if self.rect.right >= screen_rect.right:
print("Right >= right screen" +' direction is' + str(self.ai_settings.fleet_direction))
return True
elif self.rect.left <= 0:
print("Left <= left")
return True
def update(self):
"""Move the alien right or left."""
self.x += (self.ai_settings.alien_speed_factor *
self.ai_settings.fleet_direction)
self.rect.x = self.x
I'm new to pygame and sprites, I don't understand it why randit has such impact. I've placed in the code when crucial changes are about to be made print statements to debug it from console (but I dunno if it is logic problem). Anyone who can shed a light to it I would appreciate so much. Lost 2 days of learning and programming already. Running python 3.4 from Eclipse Neon on win 10 Thanks very much.
Found the mistake, indentation in func change_fleet_direction(), if block: cannot be in for loop.
This question already has answers here:
How can I know if a circle and a rect is touched in Pygame?
(1 answer)
Issue finding side of collision for Circle-Rectangle collision
(1 answer)
Detect collision between textbox and circle in pygame
(1 answer)
How do I detect collision in pygame?
(5 answers)
Sometimes the ball doesn't bounce off the paddle in pong game
(1 answer)
Closed 2 years ago.
Is there a way to handle collision detection between draw.circle and draw.rect ?
If I try to use sprite collision detection than it says circle has not got rect atrributes.
I create two players: rectangles. I create one ball: circle. I would like to handle the collision between two players and a ball in the best way possible. Could you help ?
I present my code below:
# DATE: 090215
TWO PLAYERS
CONTROL VIA KEYBOARD OR MOUSE
#
import pygame, sys
from pygame.constants import MOUSEMOTION, K_LEFT, K_RIGHT, K_DOWN, K_UP
pygame.init()
clock = pygame.time.Clock()
SCREENW = 800
SCREENH = 600
SCREEN = pygame.display.set_mode((SCREENW,SCREENH),0,32)
WHITE = (255,255,255)
BLACK = (0,0,0)
BLUE = (0,70,160)
RED = (255,0,0)
RECTH = 100
RECTW = 30
#players
PLAYER1P = (0,((SCREENH - RECTH)/2),RECTW,RECTH)
PLAYER2P = ((SCREENW-RECTW),((SCREENH - RECTH)/2),RECTW,RECTH)
# BALLS append with a ball for collision detection purposes
BALLS = []
# PLAYERS append with players for collision detection purposes
PLAYERS = []
# CLASS TO DEFINE PLAYER
class PlayerSprite(pygame.sprite.Sprite):
# define object atributes
def __init__(self,x,y,rwidth,rheight):
pygame.sprite.Sprite.__init__(self)
self.x = x
self.y = y
self.width = rwidth
self.height = rheight
# define object behavior
def update(self,control,Surface,color):
key = pygame.key.get_pressed()
self.control = control
if self.control == 1:
self.y = pygame.mouse.get_pos()[1]
if self.y >= SCREENH - RECTH:
self.y = SCREENH - RECTH
if self.control == 0:
dist = 20
if key[pygame.K_DOWN]:
self.y += dist
if key[pygame.K_UP]:
self.y -= dist
if key[pygame.K_LEFT]:
None
if key[pygame.K_RIGHT]:
None
if self.y >= SCREENH - RECTH:
self.y = SCREENH - RECTH
if self.y <= 0:
self.y = 0
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# draw player as a rectangle
# the important bit is that here you can change player shape
self.player = pygame.Rect(self.x,self.y,self.width,self.height)
pygame.draw.rect(Surface,color,self.player)
class CircleSprite(pygame.sprite.Sprite):
# define object atributes
def __init__(self,x,y,rwidth,rheight,speedx,speedy):
pygame.sprite.Sprite.__init__(self)
self.x = x
self.y = y
self.speedx = speedx
self.speedy = speedy
self.width = rwidth
self.height = rheight
# define object behavior
def update(self,Surface,color):
#self.control = control
#if self.control == 1:
# self.y = pygame.mouse.get_pos()[1]
self.x += self.speedx
self.y += self.speedy
# draw player as a rectangle
# the important bit is that here you can change player shape
pygame.draw.circle(Surface, color, (self.x, self.y), self.width, 0)
# main function
def main():
# CREATE PLAYER OBJECT before WHILE loop
prec1 = PlayerSprite(0,SCREENH/2 - RECTH/2,RECTW,RECTH)
prec2 = PlayerSprite(SCREENW - RECTW,SCREENH/2 - RECTH/2,RECTW,RECTH)
prec3 = CircleSprite(SCREENW/2,SCREENH/2,RECTW/3,RECTH/3,10,5)
PLAYERS.append(prec1)
PLAYERS.append(prec2)
BALLS.append(prec3)
while True:
# update OBJECT position
SCREEN.fill(WHITE)
# 0 = KEYBOARD
# 1 = MOUSE
prec1.update(0,SCREEN,BLUE)
prec2.update(1,SCREEN,BLACK)
prec3.update(SCREEN,RED)
# check collision
is_a_collision = pygame.sprite.collide_mask(prec1,prec3)
if is_a_collision:
print "Boom1"
# change direction
if prec3.x >= SCREENW or prec3.x <= 0:
prec3.speedx = - prec3.speedx
if prec3.y >= SCREENH or prec3.y <= 0:
prec3.speedy = - prec3.speedy
pygame.display.update()
clock.tick(50)
pygame.quit()
main()