Hexagon does not show - python

I have a problem with my code, im trying to draw a hexagon polygon, but nth show up. When i'm trying with eclipse or other pygame.draw functions its ok, problem is with polygons. Here is my code. I think whole program is working fine, the problem is here :
hexagon = Hexagon.hexagon_generator(40,self.rect.x,self.rect.y)
pygame.draw.polygon(self.image,(0,225,0),list(hexagon),0)
Whole program:
import pygame
import random
import Hexagon
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
class Player(pygame.sprite.Sprite):
def __init__(self,x,y):
super().__init__()
self.image = pygame.Surface([100,100])
self.rect = self.image.get_rect()
self.image.fill(WHITE)
self.image.set_colorkey(WHITE)
self.rect.x = x
self.rect.y = y
hexagon = Hexagon.hexagon_generator(40,self.rect.x,self.rect.y)
pygame.draw.polygon(self.image,(0,225,0),list(hexagon),0)
self.velocity_y = 0
self.velocity_x = 0
def move(self, x, y):
self.velocity_x += x
self.velocity_y += y
def update(self):
self.rect.x += self.velocity_x
self.rect.y += self.velocity_y
if self.rect.x >785:
self.rect.x =785
elif self.rect.x <0:
self.rect.x =0
elif self.rect.y > 585:
self.rect.y = 585
elif self.rect.y < 0:
self.rect.y = 0
elif self.rect.x<0 and self.rect.y < 0:
self.rect.x = 0
self.rect.y = 0
pygame.init()
screen_width = 800
screen_height = 600
screen = pygame.display.set_mode([screen_width, screen_height])
all_sprites_list = pygame.sprite.Group()
player = Player(200,200)
all_sprites_list.add(player)
done = False
clock = pygame.time.Clock()
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_DOWN:
player.move(0,5)
if event.key == pygame.K_UP:
player.move(0, -5)
if event.key == pygame.K_LEFT:
player.move(-5, 0)
if event.key == pygame.K_RIGHT:
player.move(5, 0)
if event.type == pygame.KEYUP:
if event.key == pygame.K_DOWN:
player.move(0, -5)
if event.key == pygame.K_UP:
player.move(0, 5)
if event.key == pygame.K_LEFT:
player.move(5, 0)
if event.key == pygame.K_RIGHT:
player.move(-5, 0)
screen.fill(WHITE)
all_sprites_list.update()
all_sprites_list.draw(screen)
pygame.display.flip()
clock.tick(60)
pygame.quit()
There is a Hexagon module:
import math
def hexagon_generator(edge_length, x,y):
for angle in range(0, 360, 60):
x += math.cos(math.radians(angle)) * edge_length
y += math.sin(math.radians(angle)) * edge_length
yield x, y

If you print the values that hexagon_generator yields, you'll see that the points are outside of the image (which has a size of 100*100 pixels).
[(240.0, 200.0), (260.0, 234.64101615137753), (240.0, 269.28203230275506), (200.0, 269.28203230275506), (179.99999999999997, 234.64101615137753), (199.99999999999997, 200.0)]
You shouldn't use the world coordinates of the player as the start x, y values. If the hexagon should be centered, you can just pass the half edge length of the image to the generator and add it to x and y:
def hexagon_generator(edge_length):
for angle in range(0, 360, 60):
x = math.cos(math.radians(angle)) * edge_length + edge_length
y = math.sin(math.radians(angle)) * edge_length + edge_length
yield x, y

Related

Pygame ball movement flickering

I have been trying to make a basic Pygame code where the ball bounces around the screen and off your paddle. The paddle movement is smooth, but the ball flickers and is pretty choppy. Here is my complete code:
import pygame, sys
from pygame.locals import *
import random, time
pygame.init()
window = (800, 600)
background = (0, 0, 0)
back = pygame.Surface(window)
entity_color = (255, 255, 255)
x = 362.5
y = 550
ball_x = 387.5
ball_y = 50
width = 75
height = 25
clockobject = pygame.time.Clock()
screen = pygame.display.set_mode((window))
pygame.display.set_caption("Test Game")
class Ball(pygame.sprite.Sprite):
def __init__(self):
super(Ball, self).__init__()
self.surf = pygame.Surface((25, 25))
self.surf.fill((255, 255, 255))
self.rect = self.surf.get_rect()
self.dir_x = 1
self.dir_y = 1
self.speed = 2
def update(self):
global ball_x
global ball_y
if ball_x > 775:
ball_x = 775
ball.dir_x = -1
elif ball_x < 0:
ball_x = 0
ball.dir_x = 1
if ball_y < 0:
ball_y = 0
ball.dir_y = 1
elif ball_y > 600:
ball_y = 50
ball_x = 387.5
if ball_x <= x + 75 and ball_x >= x and ball_y <= y and ball_y >= y - 25:
ball.dir_y = -1
ball_x = ball_x + ball.speed * ball.dir_x
ball_y = ball_y + ball.speed * ball.dir_y
class Player(pygame.sprite.Sprite):
def __init__(self):
super(Player, self).__init__()
self.image_s = pygame.image.load("paddle.png")
self.image_b = self.image_s.get_rect()
self.surf = pygame.Surface((75, 25))
self.surf.fill((255, 255, 255))
self.rect = self.surf.get_rect()
def update(self):
global x
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
x = x - 5
elif keys[pygame.K_RIGHT]:
x = x + 5
def checkboundaries(self):
global x
if x > 725:
x = 725
if x < 0:
x = 0
ball = Ball()
player = Player()
waiting = True
while waiting:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
elif event.key == pygame.K_SPACE:
running = True
waiting = False
while running:
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
player.update()
ball.update()
player.checkboundaries()
screen.blit(back, (0,0))
screen.blit(player.surf, (x, y))
screen.blit(ball.surf, (ball_x, ball_y))
pygame.display.flip()
clockobject.tick(360)
pygame.quit()
sys.exit()
Is this because of something wrong in my code that is running slowly, or am I missing something?
If you are using pygame.sprite.Sprite, you should also use pygame.sprite.Group.
pygame.sprite.Group.draw() and pygame.sprite.Group.update() are methods which are provided by pygame.sprite.Group.
The latter delegates to the update method of the contained pygame.sprite.Sprites — you have to implement the method. See pygame.sprite.Group.update():
Calls the update() method on all Sprites in the Group. [...]
The former uses the image and rect attributes of the contained pygame.sprite.Sprites to draw the objects — you have to ensure that the pygame.sprite.Sprites have the required attributes. See pygame.sprite.Group.draw():
Draws the contained Sprites to the Surface argument. This uses the Sprite.image attribute for the source surface, and Sprite.rect. [...]
e.g.:
import pygame, sys
from pygame.locals import *
pygame.init()
clockobject = pygame.time.Clock()
screen = pygame.display.set_mode((800, 600))
back = pygame.Surface(screen.get_size())
pygame.display.set_caption("Test Game")
class Ball(pygame.sprite.Sprite):
def __init__(self):
super(Ball, self).__init__()
self.image = pygame.Surface((25, 25))
self.image.fill((255, 255, 255))
self.rect = self.image.get_rect(topleft = (387, 50))
self.dir_x = 1
self.dir_y = 1
self.speed = 2
def update(self):
if self.rect.x > 775:
self.rect.x = 775
self.dir_x = -1
elif self.rect.x < 0:
self.rect.x = 0
self.dir_x = 1
if self.rect.y < 0:
self.rect.y = 0
self.dir_y = 1
elif self.rect.y > 600:
self.rect.topleft = (387, 50)
if self.rect.colliderect(player.rect):
ball.dir_y = -1
self.rect.x += ball.speed * ball.dir_x
self.rect.y += ball.speed * ball.dir_y
class Player(pygame.sprite.Sprite):
def __init__(self):
super(Player, self).__init__()
self.image = pygame.Surface((75, 25))
self.image.fill((255, 255, 255))
self.rect = self.image.get_rect(topleft = (363, 550))
def update(self):
keys = pygame.key.get_pressed()
self.rect.x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * 5
self.rect.clamp_ip(screen.get_rect())
ball = Ball()
player = Player()
all_sprites = pygame.sprite.Group([ball, player])
started = False
running = True
while running:
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_SPACE:
started = True
screen.blit(back, (0,0))
if started:
all_sprites.update()
all_sprites.draw(screen)
pygame.display.flip()
clockobject.tick(100)
pygame.quit()
sys.exit()

My Simple Platformer Character Drifts Left but not Right and I Can't Find the Bug That Causes It [duplicate]

This question already has answers here:
Pygame doesn't let me use float for rect.move, but I need it
(2 answers)
Simple drag physics, acting differently when moving left or right [duplicate]
(1 answer)
Closed 2 years ago.
Basically I am working on a simple platformer and I have all of the basics like the gravity, acceleration, and platforms, but for some reason the character will decelerate going right, but when it goes left it will continue moving slowly instead of stopping. I even printed the value of my variable "changeX" to see what was going on, and it showed me the values I that should be happening rather than what was displayed. Sorry my comments are very limited in their helpfulness. The code regarding variables rect.x , changeX, and accelX are likely the most relevant.
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
BLUE = (50, 50, 255)
# Screen dimensions
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
COLOR = BLUE
#Top Speed
tSpeedX = 7
tSpeedY = 20
#gravity constant
gConstant = 1
#acceleration X variable
accelX = 0
#acceleration Y variable
accelY = 0
#whether you can jump or not
jumpB = True
class player(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
#iniatilized values for rect
self.image = pygame.Surface([50, 50])
self.image.fill(COLOR)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.changeX = 0
self.changeY = 0
self.walls = None
#the velocity function. X and Y values are assigned based on the accelX
#and Y constants and added to the points of the rectangle
def velocity(self,x,y):
#change in speed
self.changeX += x
self.changeY += y
if abs(self.changeX) >= tSpeedX:
self.changeX = self.changeX/abs(self.changeX) * tSpeedX
if abs(self.changeY) >= tSpeedY:
self.changeY = self.changeY/abs(self.changeY) * tSpeedY
#standard update function. Will update rectangles position and deaccelerate it if no key held
def jump(self,y):
self.changeY = y
def update(self):
if accelX == 0:
self.changeX *= 0.92
if accelY == 0:
self.changeY *= .95
self.rect.x += self.changeX
print(self.changeX)
block_hit_list = pygame.sprite.spritecollide(self, self.walls, False)
for block in block_hit_list:
if self.changeX > 0:
self.rect.right = block.rect.left
else:
self.rect.left = block.rect.right
self.rect.y += self.changeY + (9*gConstant)
block_hit_list = pygame.sprite.spritecollide(self, self.walls, False)
for block in block_hit_list:
if self.changeY >= -5:
global jumpB
jumpB = True
COLOR = WHITE
self.rect.bottom = block.rect.top
else:
self.rect.top = block.rect.bottom
class wall(pygame.sprite.Sprite):
def __init__(self, sx, sy,px,py):
super().__init__()
#iniatilized values for walls
collision = False
self.image = pygame.Surface([sx, sy])
self.image.fill(WHITE)
self.rect = self.image.get_rect()
self.rect.x = px
self.rect.y = py
pygame.init()
screen = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT])
spriteList = pygame.sprite.Group()
wallList = pygame.sprite.Group()
Player = player(100,100)
spriteList.add(Player)
Wall1 = wall(1000, 30, 0, 400)
Wall2 = wall(100, 30, 150, 350)
wallList.add(Wall2)
spriteList.add(Wall2)
wallList.add(Wall1)
spriteList.add(Wall1)
Player.walls = wallList
clock = pygame.time.Clock()
#Allows program to exit
quit = False
while not quit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit = True
#Sets accel values
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
accelX = -.25
if event.key == pygame.K_RIGHT:
accelX = .25
if event.key == pygame.K_UP and jumpB == True:
Player.jump(-20)
jumpB = False
COLOR = BLUE
if event.key == pygame.K_DOWN:
accelY = .25
#reverses accel values to allow for deaccleration
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
accelX = 0
if event.key == pygame.K_RIGHT:
accelX = 0
if event.key == pygame.K_UP:
accelY = 0
if event.key == pygame.K_DOWN:
accelY = 0
#calls function to move rectangle
Player.velocity(accelX, accelY)
spriteList.update()
screen.fill(BLACK)
spriteList.draw(screen)
pygame.display.flip()
clock.tick(60)

Pygame Movement of Flag and Character With Walls

I am making a capture the flag type game. From the code below, I have the fundamentals set up. However, I don't know how I stop the flag from moving when the character hits a wall. Can anyone help me with this? As you can see if you run the code, the flag is effectively picked up by the character and carried but the flag will not stop if the character hits a wall. I want the flag to stay on the right side of the character as well. Thanks for any help. (CODE HAS BEEN UPDATED SINCE ORIGINAL POST)
import pygame
def start():
pygame.init()
BLUE = (0, 0, 128)
RED = (204, 0, 0)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
screen = pygame.display.set_mode((1920,1080), flags=pygame.FULLSCREEN)
pygame.display.set_caption("Recovery")
clock = pygame.time.Clock()
bigJoe = pygame.image.load("bigJoe.png")
characterSelected = bigJoe
game(BLACK, WHITE, BLUE, RED, screen, clock, characterSelected, bigJoe)
def game(BLACK, WHITE, BLUE, RED, screen, clock, characterSelected, bigJoe):
if characterSelected == bigJoe:
gameCharacter = "gameJoe.png"
all_sprite_list = pygame.sprite.Group()
playerList = pygame.sprite.Group()
wall_list = pygame.sprite.Group()
flagList = pygame.sprite.Group()
playerFlag = pygame.sprite.Group()
flag = Flag(1810,540)
flagList.add(flag)
'''Design of Map Below'''
topWall = Wall(0, 0, 1920, 5, BLUE)
bottomWall = Wall(0, 1075, 1920, 5, BLUE)
leftWall = Wall(0, 0, 5, 1080, BLUE)
rightWall = Wall(1915, 0, 5, 1080, BLUE)
baseWall1 = Wall(5, 300, 150, 75, WHITE)
baseWall2 = Wall(5, 375, 100, 330, WHITE)
baseWall3 = Wall(5, 705, 150, 75, WHITE)
baseSquare = Wall(30, 530, 40, 40, RED)
wall1 = Wall(400, 400, 200, 300, RED)
wall_list.add(topWall, bottomWall, leftWall, rightWall, baseWall1, wall1, baseWall2, baseWall3)
all_sprite_list.add(topWall, bottomWall, leftWall, rightWall, baseWall1, wall1, baseWall2, baseWall3, baseSquare, flag)
'''Adding Character to Game'''
player = Player(110, 550, gameCharacter)
flag.player = playerFlag
player.wall = wall_list
all_sprite_list.add(player)
playerFlag.add(player, flag)
playerList.add(player)
flag.player = player
flag.carried = playerFlag
flag.walls = wall_list
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
if keys[pygame.K_ESCAPE]:
run = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player.changespeed(-3, 0)
flag.moveFlag(-3, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(3, 0)
flag.moveFlag(3, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, -3)
flag.moveFlag(0, -3,)
elif event.key == pygame.K_DOWN:
player.changespeed(0, 3)
flag.moveFlag(0, 3)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.changespeed(3, 0)
flag.moveFlag(3, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(-3, 0)
flag.moveFlag(-3, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, 3)
flag.moveFlag(0, 3)
elif event.key == pygame.K_DOWN:
player.changespeed(0, -3)
flag.moveFlag(0, -3)
all_sprite_list.update()
screen.fill(BLACK)
all_sprite_list.draw(screen)
pygame.display.flip()
clock.tick(75)
start()
On a separate file
import pygame
class Player(pygame.sprite.Sprite):
def __init__(self, x, y, gameCharacter):
super().__init__()
self.image = pygame.image.load(gameCharacter)
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
self.change_x = 0
self.change_y = 0
self.wall = None
def changespeed(self, x, y):
self.change_x += x
self.change_y += y
def update(self):
self.rect.x += self.change_x
wallHitList = pygame.sprite.spritecollide(self, self.wall, False)
for wall in wallHitList:
if self.change_x > 0:
self.rect.right = wall.rect.left
else:
self.rect.left = wall.rect.right
self.rect.y += self.change_y
wallHitList = pygame.sprite.spritecollide(self, self.wall, False)
for wall in wallHitList:
if self.change_y > 0:
self.rect.bottom = wall.rect.top
else:
self.rect.top = wall.rect.bottom
class Wall(pygame.sprite.Sprite):
def __init__(self, x, y, width, height,color):
super().__init__()
self.image = pygame.Surface([width, height])
self.image.fill(color)
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
class Flag(pygame.sprite.Sprite):
def __init__(self, x, y,):
super().__init__()
self.image = pygame.image.load("flag.png")
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
self.change_x = 0
self.change_y = 0
def moveFlag(self, x, y):
self.change_x += x
self.change_y += y
def update(self):
hit = False
allowMove = True
flagCharacterList = pygame.sprite.spritecollide(self, self.carried, False)
for i in flagCharacterList:
if len(flagCharacterList) == 2:
hit = True
else:
hit = False
block_hit_list = pygame.sprite.groupcollide(self.walls, self.carried, False, False)
for block in block_hit_list:
if len(block_hit_list) == 1:
allowMove = False
else:
allowMove = True
if hit and allowMove:
self.rect.x += self.change_x
self.rect.y += self.change_y
The flag doesn't move bit itself. bit the player carries the flag. Possibly the player can carry more than 1 flag.
Remove the collision detection from the method Flag.update:
class Flag(pygame.sprite.Sprite):
def __init__(self, x, y,):
super().__init__()
#self.image = pygame.image.load("flag.png")
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
self.change_x = 0
self.change_y = 0
def moveFlag(self, x, y):
self.change_x += x
self.change_y += y
def update(self):
self.rect.x += self.change_x
self.rect.y += self.change_y
Add an attribute self.flags to the player and move all the flags contained in the list by the same amount as the player:
class Player(pygame.sprite.Sprite):
def __init__(self, x, y, gameCharacter):
# [...]
self.flags = []
# [...]
def update(self):
current_pos = (self.rect.x, self.rect.y)
self.rect.x += self.change_x
wallHitList = pygame.sprite.spritecollide(self, self.wall, False)
for wall in wallHitList:
if self.change_x > 0:
self.rect.right = wall.rect.left
else:
self.rect.left = wall.rect.right
self.rect.y += self.change_y
wallHitList = pygame.sprite.spritecollide(self, self.wall, False)
for wall in wallHitList:
if self.change_y > 0:
self.rect.bottom = wall.rect.top
else:
self.rect.top = wall.rect.bottom
for flag in self.flags:
flag.rect.x += self.rect.x - current_pos[0]
flag.rect.y += self.rect.y - current_pos[1]
flag.move() is not needed any more. But if the player hits the flag, then the flag is add player.flags. That caused, that the plyer carries the flag:
def game(BLACK, WHITE, BLUE, RED, screen, clock, characterSelected, bigJoe):
# [...]
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
if keys[pygame.K_ESCAPE]:
run = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT: player.changespeed(-3, 0)
elif event.key == pygame.K_RIGHT: player.changespeed(3, 0)
elif event.key == pygame.K_UP: player.changespeed(0, -3)
elif event.key == pygame.K_DOWN: player.changespeed(0, 3)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT: player.changespeed(3, 0)
elif event.key == pygame.K_RIGHT: player.changespeed(-3, 0)
elif event.key == pygame.K_UP: player.changespeed(0, 3)
elif event.key == pygame.K_DOWN: player.changespeed(0, -3)
if flag not in player.flags:
if pygame.sprite.collide_rect(flag, player):
player.flags.append(flag)
flag.rect.left = player.rect.right
# [...]

How to get camera following a top down car in pygame

new to pygame and game programming in general, just wondered how I could get a camera to follow a car (nothing fancy) in a top down car game - think Micro Machines! I'm using Python 3.6, and have got a bike rotating, and moving around. I've kept the code here shorter but I do have a static image for reference if the camera worked!
Here's what I have:
import pygame, math, sys, random
from pygame.locals import *
display_width = 1280
display_height = 800
# Sets size of screen
screen = pygame.display.set_mode((display_width, display_height))
# Initialises clock
clock = pygame.time.Clock()
# Colours
white = (255,255,255)
black = (0,0,0)
class Entity(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
class VehicleSprite(Entity):
# Creates a vehicle class
MAX_FORWARD_SPEED = 10
MAX_REVERSE_SPEED = 2
ACCELERATION = 0.05
TURN_SPEED = 0.000000000001
def __init__(self, image, position):
Entity.__init__(self)
# Creates object instance off
pygame.sprite.Sprite.__init__(self)
self.src_image = pygame.image.load(image)
self.position = position
self.speed = self.direction = 0
self.k_left = self.k_right = self.k_down = self.k_up = 0
def update(self, time):
# SIMULATION
self.speed += (self.k_up +self.k_down)
if self.speed > self.MAX_FORWARD_SPEED:
self.speed = self.MAX_FORWARD_SPEED
if self.speed < -self.MAX_REVERSE_SPEED:
self.speed = -self.MAX_REVERSE_SPEED
# Degrees sprite is facing (direction)
self.direction += (self.k_right + self.k_left)
x, y = self.position
rad = self.direction * math.pi / 180
x += -self.speed*math.sin(rad)
y += -self.speed*math.cos(rad)
self.position = (x, y)
self.image = pygame.transform.rotate(self.src_image, self.direction)
self.rect = self.image.get_rect()
self.rect.center = self.position
class Background(pygame.sprite.Sprite):
def __init__(self, image_file, location):
pygame.sprite.Sprite.__init__(self) #call Sprite initializer
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
rect = screen.get_rect()
# Background
BackGround = Background('/home/pi/gametuts/images/backgrounds/bkg_img.png', [0, 0])
# Bike image load
bike = VehicleSprite('/home/pi/gametuts/images/BikePixelBig.png', rect.center)
bike_group = pygame.sprite.RenderPlain(bike)
# Ball image load
ball = VehicleSprite('/home/pi/gametuts/images/ironball.png', rect.center)
ball_group = pygame.sprite.RenderPlain(ball)
# Main game loop
def game_loop():
while 1:
#USER INPUT
# Sets frame rate
time = clock.tick(60)
for event in pygame.event.get():
if not hasattr(event, 'key'): continue
down = event.type == KEYDOWN
# Bike Input (Player 1)
if event.key == K_d: bike.k_right = down * -5
elif event.key == K_a: bike.k_left = down * 5
elif event.key == K_w: bike.k_up = down * 2
elif event.key == K_s: bike.k_down = down * -2
# Quit
elif event.key == K_ESCAPE: sys.exit(0)
#RENDERING
# Game background
screen.fill(white)
screen.blit(BackGround.image, BackGround.rect)
# Bike render
bike_group.update(time)
bike_group.draw(screen)
ball_group.update(time)
ball_group.draw(screen)
pygame.display.flip()
game_loop()
pygame.quit()
quit()
Thanks in advance!
The simplest way to implement a camera is to use a pygame.math.Vector2 as the camera, subtract the player velocity from it each frame and add it to the position of all game elements during the blitting.
import pygame as pg
from pygame.math import Vector2
class Player(pg.sprite.Sprite):
def __init__(self, pos, walls, *groups):
super().__init__(*groups)
self.image = pg.Surface((30, 50))
self.image.fill(pg.Color('dodgerblue'))
self.rect = self.image.get_rect(center=pos)
self.vel = Vector2(0, 0)
self.pos = Vector2(pos)
self.walls = walls
self.camera = Vector2(0, 0)
def update(self):
self.camera -= self.vel # Change the camera pos if we're moving.
# Horizontal movement.
self.pos.x += self.vel.x
self.rect.centerx = self.pos.x
# Change the rect and self.pos coords if we touched a wall.
for wall in pg.sprite.spritecollide(self, self.walls, False):
if self.vel.x > 0:
self.rect.right = wall.rect.left
elif self.vel.x < 0:
self.rect.left = wall.rect.right
self.pos.x = self.rect.centerx
self.camera.x += self.vel.x # Also move the camera back.
# Vertical movement.
self.pos.y += self.vel.y
self.rect.centery = self.pos.y
for wall in pg.sprite.spritecollide(self, self.walls, False):
if self.vel.y > 0:
self.rect.bottom = wall.rect.top
elif self.vel.y < 0:
self.rect.top = wall.rect.bottom
self.pos.y = self.rect.centery
self.camera.y += self.vel.y
class Wall(pg.sprite.Sprite):
def __init__(self, x, y, w, h, *groups):
super().__init__(*groups)
self.image = pg.Surface((w, h))
self.image.fill(pg.Color('sienna2'))
self.rect = self.image.get_rect(topleft=(x, y))
def main():
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
all_sprites = pg.sprite.Group()
walls = pg.sprite.Group()
for rect in ((100, 170, 90, 20), (200, 100, 20, 140),
(400, 60, 150, 100), (300, 470, 150, 100)):
walls.add(Wall(*rect))
all_sprites.add(walls)
player = Player((320, 240), walls, all_sprites)
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
elif event.type == pg.KEYDOWN:
if event.key == pg.K_d:
player.vel.x = 5
elif event.key == pg.K_a:
player.vel.x = -5
elif event.key == pg.K_w:
player.vel.y = -5
elif event.key == pg.K_s:
player.vel.y = 5
elif event.type == pg.KEYUP:
if event.key == pg.K_d and player.vel.x > 0:
player.vel.x = 0
elif event.key == pg.K_a and player.vel.x < 0:
player.vel.x = 0
elif event.key == pg.K_w and player.vel.y < 0:
player.vel.y = 0
elif event.key == pg.K_s and player.vel.y > 0:
player.vel.y = 0
all_sprites.update()
screen.fill((30, 30, 30))
for sprite in all_sprites:
# Add the player's camera offset to the coords of all sprites.
screen.blit(sprite.image, sprite.rect.topleft+player.camera)
pg.display.flip()
clock.tick(30)
if __name__ == '__main__':
pg.init()
main()
pg.quit()
Edit: Here's your code example with a camera. I've also tried to improve a few more things, for example the max(min(...)) trick to clamp the speed value. I'm not sure if the movement works as you want, but you can of course adjust it yourself. (I'd probably make even more modifications to the update method.)
import math
import random
import pygame
pygame.init()
screen = pygame.display.set_mode((1280, 800))
rect = screen.get_rect()
clock = pygame.time.Clock()
WHITE = pygame.Color('white')
# Load images globally and reuse them in your program.
# Also use the `.convert()` or `.convert_alpha()` methods after
# loading the images to improve the performance.
VEHICLE1 = pygame.Surface((40, 70), pygame.SRCALPHA)
VEHICLE1.fill((130, 180, 20))
VEHICLE2 = pygame.Surface((40, 70), pygame.SRCALPHA)
VEHICLE2.fill((200, 120, 20))
BACKGROUND = pygame.Surface((1280, 800))
BACKGROUND.fill((30, 30, 30))
class Entity(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
class VehicleSprite(Entity):
MAX_FORWARD_SPEED = 10
MAX_REVERSE_SPEED = 2
ACCELERATION = 0.05
TURN_SPEED = 0.000000000001
def __init__(self, image, position):
Entity.__init__(self)
self.src_image = image
self.image = image
self.rect = self.image.get_rect(center=position)
self.position = pygame.math.Vector2(position)
self.velocity = pygame.math.Vector2(0, 0)
self.speed = self.direction = 0
self.k_left = self.k_right = self.k_down = self.k_up = 0
def update(self, time):
# SIMULATION
self.speed += self.k_up + self.k_down
# To clamp the speed.
self.speed = max(-self.MAX_REVERSE_SPEED,
min(self.speed, self.MAX_FORWARD_SPEED))
# Degrees sprite is facing (direction)
self.direction += (self.k_right + self.k_left)
rad = math.radians(self.direction)
self.velocity.x = -self.speed*math.sin(rad)
self.velocity.y = -self.speed*math.cos(rad)
self.position += self.velocity
self.image = pygame.transform.rotate(self.src_image, self.direction)
self.rect = self.image.get_rect(center=self.position)
class Background(pygame.sprite.Sprite):
def __init__(self, image, location):
pygame.sprite.Sprite.__init__(self)
self.image = image
self.rect = self.image.get_rect(topleft=location)
def game_loop():
background = Background(BACKGROUND, [0, 0])
bike = VehicleSprite(VEHICLE1, rect.center)
ball = VehicleSprite(VEHICLE2, rect.center)
bike_group = pygame.sprite.Group(bike)
ball_group = pygame.sprite.Group(ball)
all_sprites = pygame.sprite.Group(bike_group, ball_group)
camera = pygame.math.Vector2(0, 0)
done = False
while not done:
time = clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
# Bike Input (Player 1)
if event.key == pygame.K_d:
bike.k_right = -5
elif event.key == pygame.K_a:
bike.k_left = 5
elif event.key == pygame.K_w:
bike.k_up = 2
elif event.key == pygame.K_s:
bike.k_down = -2
elif event.key == pygame.K_ESCAPE:
done = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_d:
bike.k_right = 0
elif event.key == pygame.K_a:
bike.k_left = 0
elif event.key == pygame.K_w:
bike.k_up = 0
elif event.key == pygame.K_s:
bike.k_down = 0
camera -= bike.velocity
all_sprites.update(time)
screen.fill(WHITE)
screen.blit(background.image, background.rect)
for sprite in all_sprites:
screen.blit(sprite.image, sprite.rect.topleft+camera)
pygame.display.flip()
game_loop()
pygame.quit()

I am making a pygame version of galaga. There is a weird error(see below)

This is the error:
Traceback (most recent call last):
File "C:/Users/Lucas/PycharmProjects/FirstPyGame/Main.py", line 117, in <module>
player.changespeed(3, 0)
File "C:/Users/Lucas/PycharmProjects/FirstPyGame/Main.py", line 42, in changespeed
self.change_x += x
AttributeError: 'Ship' object has no attribute 'change_x'
Here is my code:
import pygame
import random
pygame.init()
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 255, 255)
size = [800, 600]
x_coord = 400
y_coord = 600
x_speed = 0
y_speed = 0
font = pygame.font.SysFont("Calibri", 25, True, False)
snow_list = []
for i in range(50):
x = random.randrange(0, 800)
y = random.randrange(0, 600)
snow_list.append([x, y])
pygame.display.set_caption("Star Fighter")
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()
class Ship(pygame.sprite.Sprite):
def ___init__(self, x, y):
super().__init__()
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.change_x = 0
self.change_y = 0
def changespeed(self, x, y):
self.change_x += x
self.change_y += y
def update(self):
self.rect.x += self.change_x
self.rect.y += self.change_y
def DrawShip(screen, x, y):
a = pygame.draw.rect(screen, WHITE, ((x_coord - 5), (y_coord - 60), 10, 10))
b = pygame.draw.rect(screen, WHITE, ((x_coord - 15), (y_coord - 50), 10, 10))
c = pygame.draw.rect(screen, RED, ((x_coord - 5), (y_coord - 50), 10, 10))
d = pygame.draw.rect(screen, WHITE, ((x_coord + 5), (y_coord - 50), 10, 10))
class Block(pygame.sprite.Sprite):
def __init__(self, color):
super().__init__()
self.image = pygame.Surface([20, 15])
self.image.fill(color)
self.rect = self.image.get_rect()
def ScrollStars():
for i in range(len(snow_list)):
pygame.draw.circle(screen, WHITE, snow_list[i], 3)
snow_list[i][1] += 1
if snow_list[i][1] > 600:
y = random.randrange(-50, -10)
snow_list[i][1] = y
x = random.randrange(0, 800)
snow_list[i][0] = x
class Bullet(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface([4, 10])
self.image.fill(WHITE)
self.rect = self.image.get_rect()
def update(self):
self.rect.y -= 3
all_sprites_list = pygame.sprite.Group()
block_list = pygame.sprite.Group()
bullet_list = pygame.sprite.Group()
for i in range(50):
# This represents a block
block = Block(BLUE)
# Set a random location for the block
block.rect.x = random.randrange(800)
block.rect.y = random.randrange(300)
# Add the block to the list of objects
block_list.add(block)
all_sprites_list.add(block)
score = 0
player = Ship()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player.changespeed(-3, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(3, 0)
elif event.key == pygame.K_SPACE:
bullet = Bullet()
bullet.rect.x = x_coord
bullet.rect.y = 550
all_sprites_list.add(bullet)
bullet_list.add(bullet)
elif event.key == pygame.K_q:
running = False
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.changespeed(3, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(-3, 0)
if event.key == pygame.K_LEFT or pygame.K_RIGHT:
x_speed = 0
if event.type == pygame.K_UP or pygame.K_DOWN:
y_speed = 0
for bullet in bullet_list:
block_hit_list = pygame.sprite.spritecollide(bullet, block_list, True)
for block in block_hit_list:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
score += 1
if bullet.rect.y < -10:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
x_coord = x_coord + x_speed
y_coord = y_coord + y_speed
all_sprites_list.update()
screen.fill(BLACK)
all_sprites_list.draw(screen)
Ship.DrawShip(screen, x_coord, y_coord)
pygame.display.update()
clock.tick(70)
pygame.quit()
Could someone explain the error that I am having? I am a beginner and I do not understand it very well. It says that the Ship class has no attribute 'change_x' but it does, right? Sorry if this doesn't make any sense, but someone please help me with this. I would really appreciate it.
The issue is caused by a typo. The name of the constructor is __init__ rather than ___init__:
def ___init__(self, x, y):
def __init__(self, x, y):

Categories