How to rotate image while moving in pygame - python

I am new to pygame and trying to develop a game in which the player moves with arrow keys and rotates around with the position of mouse (like mini miltia). But I am able to rotate the player but not able to move it around. It is only showing the player with rotation but it is not moving.
def rot_center(image, rect, angle):
rot_image = pygame.transform.rotate(image, angle)
rot_rect = rot_image.get_rect(center=rect.center)
return rot_image, rot_rect
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image_orig = load_image('player.png')
self.image = self.image_orig
self.rect = self.image.get_rect()
self.rect_orig = self.rect
self.mask = pygame.mask.from_surface(self.image)
self.x, self.y = int(pygame.display.Info().current_w / 2), int(pygame.display.Info().current_h / 2)
self.rect.topleft = self.x, self.y
self.health = 100
self.damage_done = 0
self.chspeed_x = 10
self.chspeed_y = 10
self.dir = 0
def rot_aim(self, tx, ty):
self.dir = (math.atan2(self.y - ty, self.x - tx) * 180 / PI)
self.image, self.rect = rot_center(self.image_orig, self.rect_orig, self.dir)
def move(self, dx, dy):
self.chspeed_x = dx
self.chspeed_y = dy
self.x = self.x + self.chspeed_x * math.cos(math.radians(270 - self.dir))
self.y = self.y + self.chspeed_y * math.cos(math.radians(270 - self.dir))
def main():
pygame.init()
screen = pygame.display.set_mode((800, 600))
clock = pygame.time.Clock()
FPS = 30
paused = False
player = Player()
player_s = pygame.sprite.Group()
player_s.add(player)
while not paused:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.MOUSEMOTION:
mousepos = pygame.mouse.get_pos()
mouseX = mousepos[0]
mouseY = mousepos[1]
player.rot_aim(mousepos[1], mousepos[0])
if event.type == pygame.KEYDOWN:
if event.type == pygame.K_UP:
player.move(0, 10)
if event.type == pygame.K_DOWN:
player.move(0, -10)
if event.type == pygame.K_RIGHT:
player.move(10, 0)
if event.type == pygame.K_LEFT:
player.move(-10, 0)
player_s.draw(screen)
clock.tick(FPS)
pygame.display.flip()

You missed to update self.rect after rotating or moving the player. Actually the position of the player (self.x, self.y) is changed. But since self.rect is used to draw the player, this attribute has to be updated by the position. The position has to be round, because a pygame.Rect object stores integral values:
class Player(pygame.sprite.Sprite):
# [...]
def rot_aim(self, tx, ty):
self.dir = (math.atan2(self.y - ty, self.x - tx) * 180 / PI)
self.image, self.rect = rot_center(self.image_orig, self.rect_orig, self.dir)
self.rect.center = round(self.x), round(self.y) # <--- this is missing
def move(self, dx, dy):
self.chspeed_x = dx
self.chspeed_y = dy
self.x = self.x + self.chspeed_x * math.cos(math.radians(270 - self.dir))
self.y = self.y + self.chspeed_y * math.cos(math.radians(270 - self.dir))
self.rect.center= round(self.x), round(self.y) # <--- this is missing
Further more there is a typo. You have to compare event.key to the button rather than event.type
For instance:
if event.type == pygame.K_UP:
if event.key == pygame.K_UP:
# [...]
Anyway I recommend to use pygame.key.get_pressed() rather than the button events, to achieve a continuously and smooth movement.
Finally clear the background by screen.fill(0) before drawing the scene:
def main():
# [...]
while not paused:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.MOUSEMOTION:
mousepos = pygame.mouse.get_pos()
mouseX = mousepos[0]
mouseY = mousepos[1]
player.rot_aim(mousepos[1], mousepos[0])
keys = pygame.key.get_pressed()
if keys[pygame.K_UP]:
player.move(0, -10)
if keys[pygame.K_DOWN]:
player.move(0, 10)
if keys[pygame.K_RIGHT]:
player.move(10, 0)
if keys[pygame.K_LEFT]:
player.move(-10, 0)
screen.fill(0)
player_s.draw(screen)
clock.tick(FPS)
pygame.display.flip()

Related

Pygame bullets strange behavior - they multiplies their dmg and speed [duplicate]

Heres my code
import pygame, os
os.environ["SDL_VIDEO_CENTERED"] = "1"
pygame.init()
win = pygame.display
d = win.set_mode((1200, 600))
class player:
def __init__(self, x, y, height, width):
self.x = x
self.y = y
self.height = height
self.width = width
self.speed = 2
def draw(self):
pygame.draw.rect(d, (0, 0, 0), (self.x, self.y, self.width, self.height))
def move_left(self):
self.x -= self.speed
def move_right(self):
self.x += self.speed
class bullet:
def __init__(self):
self.radius = 10
self.speed = 20
def shoot(self):
x = p.x
y = p.y
self.shooting = True
while self.shooting:
d.fill((98, 98, 98))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
y -= self.speed
pygame.draw.circle(d, (255, 0, 0), (x, y), self.radius)
pygame.time.Clock().tick(100)
win.update()
if y <= 0:
self.shooting = False
b = bullet()
p = player(600, 500, 50, 30)
while True:
d.fill((98, 98, 98))
p.draw()
for event in pygame.event.get():
pass
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
b.shoot()
if event.key == pygame.K_LEFT:
p.move_left()
if event.key == pygame.K_RIGHT:
p.move_right()
win.update()
This is what i could come up with after a few Trial and errors but it is really uneffective. Firstly the player disappers when i press space bar. I guess this is obvious as i have a different loops for shooting and player but i dont know how to get around it and implement both shooting and player in the same loop.
The second probllem i am having is breaking the while self.shooting: loop. I tried breaking it when y reaches a certain point by doing this
if y <= 0:
self.shooting = False
but this dosent break. Instead, it restarts the loop all over again.
Another weird problem i am having is that everytime i move mouse(slightly fast) or press a bunch of buttons at once, it breaks the while self.shooting loop.
The general approach to firing bullets is to store the positions of the bullets in a list (bullet_list). When a bullet is fired, add the bullet's starting position ([start_x, start_y]) to the list. The starting position is the position of the object (player or enemy) that fires the bullet. Use a for-loop to iterate through all the bullets in the list. Move position of each individual bullet in the loop. Remove a bullet from the list that leaves the screen (bullet_list.remove(bullet_pos)). For this reason, a copy of the list (bullet_list[:]) must be run through (see How to remove items from a list while iterating?). Use another for-loop to blit the remaining bullets on the screen:
bullet_list = []
while run == True:
# [...]
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
bullet_list.append([start_x, start_y])
for bullet_pos in bullet_list[:]:
bullet_pos[0] += move_bullet_x
bullet_pos[1] += move_bullet_y
if not screen.get_rect().colliderect(bullet_image.get_rect(center = bullet_pos))
bullet_list.remove(bullet_pos)
# [...]
for bullet_pos in bullet_list[:]
screen.blit(bullet_image, bullet_image.get_rect(center = bullet_pos))
# [...]
See also Shoot bullet.
Please note, that class names should normally use the CapWords convention.
(See Style Guide for Python Code - Class names)
That means it has to be Player and Bullet rather than player and bullet
You have an application loop, so use it. All the objects are continuously updated and drawn in the main application loop, in each frame.
The class Bullet do not need any loop. The constructor has to have parameters for the position (x, y). Further it needs on method which changes the position and one which draws the bullet:
class Bullet:
def __init__(self, x, y):
self.radius = 10
self.speed = 10
self.x = x
self.y = y
def update(self):
self.y -= self.speed#
def draw(self):
pygame.draw.circle(d, (255, 0, 0), (self.x, self.y), self.radius)
Use a list of bullets. Create a new bullet when space is pressed. Move the bullets (update) in every frame an remove a bullet if it is out of the window. Draw the remaining bullets in every frame:
bullets = []
# [...]
while run:
for event in pygame.event.get():
# [...]
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
bullets.append(Bullet(p.x+p.width//2, p.y))
# [...]
for b in bullets:
b.update()
if b.y < 0:
bullets.remove(b)
# [...]
for b in bullets:
b.draw()
Furthermore use pygame.key.get_pressed() use to get the state of the keys in every frame and to update the position of the player:
while run:
# [...]
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
p.move_left()
if keys[pygame.K_RIGHT]:
p.move_right()
Complete example:
import pygame, os
os.environ["SDL_VIDEO_CENTERED"] = "1"
pygame.init()
win = pygame.display
d = win.set_mode((1200, 600))
clock = pygame.time.Clock()
class Player:
def __init__(self, x, y, height, width):
self.x = x
self.y = y
self.height = height
self.width = width
self.speed = 2
def draw(self):
pygame.draw.rect(d, (0, 0, 0), (self.x, self.y, self.width, self.height))
def move_left(self):
self.x -= self.speed
def move_right(self):
self.x += self.speed
class Bullet:
def __init__(self, x, y):
self.radius = 10
self.speed = 10
self.x = x
self.y = y
def update(self):
self.y -= self.speed#
def draw(self):
pygame.draw.circle(d, (255, 0, 0), (self.x, self.y), self.radius)
bullets = []
p = Player(600, 500, 50, 30)
run = True
while run:
clock.tick(100)
# handel events
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
bullets.append(Bullet(p.x+p.width//2, p.y))
# update objects
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
p.move_left()
if keys[pygame.K_RIGHT]:
p.move_right()
for b in bullets:
b.update()
if b.y < 0:
bullets.remove(b)
# clear display
d.fill((98, 98, 98))
# draw scene
for b in bullets:
b.draw()
p.draw()
# update display
win.update()

I'm creating Space Invader game and I'm unable to fire bullets. I'm following a tutorial by freecodecamp on youtube [duplicate]

Heres my code
import pygame, os
os.environ["SDL_VIDEO_CENTERED"] = "1"
pygame.init()
win = pygame.display
d = win.set_mode((1200, 600))
class player:
def __init__(self, x, y, height, width):
self.x = x
self.y = y
self.height = height
self.width = width
self.speed = 2
def draw(self):
pygame.draw.rect(d, (0, 0, 0), (self.x, self.y, self.width, self.height))
def move_left(self):
self.x -= self.speed
def move_right(self):
self.x += self.speed
class bullet:
def __init__(self):
self.radius = 10
self.speed = 20
def shoot(self):
x = p.x
y = p.y
self.shooting = True
while self.shooting:
d.fill((98, 98, 98))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
y -= self.speed
pygame.draw.circle(d, (255, 0, 0), (x, y), self.radius)
pygame.time.Clock().tick(100)
win.update()
if y <= 0:
self.shooting = False
b = bullet()
p = player(600, 500, 50, 30)
while True:
d.fill((98, 98, 98))
p.draw()
for event in pygame.event.get():
pass
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
b.shoot()
if event.key == pygame.K_LEFT:
p.move_left()
if event.key == pygame.K_RIGHT:
p.move_right()
win.update()
This is what i could come up with after a few Trial and errors but it is really uneffective. Firstly the player disappers when i press space bar. I guess this is obvious as i have a different loops for shooting and player but i dont know how to get around it and implement both shooting and player in the same loop.
The second probllem i am having is breaking the while self.shooting: loop. I tried breaking it when y reaches a certain point by doing this
if y <= 0:
self.shooting = False
but this dosent break. Instead, it restarts the loop all over again.
Another weird problem i am having is that everytime i move mouse(slightly fast) or press a bunch of buttons at once, it breaks the while self.shooting loop.
The general approach to firing bullets is to store the positions of the bullets in a list (bullet_list). When a bullet is fired, add the bullet's starting position ([start_x, start_y]) to the list. The starting position is the position of the object (player or enemy) that fires the bullet. Use a for-loop to iterate through all the bullets in the list. Move position of each individual bullet in the loop. Remove a bullet from the list that leaves the screen (bullet_list.remove(bullet_pos)). For this reason, a copy of the list (bullet_list[:]) must be run through (see How to remove items from a list while iterating?). Use another for-loop to blit the remaining bullets on the screen:
bullet_list = []
while run == True:
# [...]
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
bullet_list.append([start_x, start_y])
for bullet_pos in bullet_list[:]:
bullet_pos[0] += move_bullet_x
bullet_pos[1] += move_bullet_y
if not screen.get_rect().colliderect(bullet_image.get_rect(center = bullet_pos))
bullet_list.remove(bullet_pos)
# [...]
for bullet_pos in bullet_list[:]
screen.blit(bullet_image, bullet_image.get_rect(center = bullet_pos))
# [...]
See also Shoot bullet.
Please note, that class names should normally use the CapWords convention.
(See Style Guide for Python Code - Class names)
That means it has to be Player and Bullet rather than player and bullet
You have an application loop, so use it. All the objects are continuously updated and drawn in the main application loop, in each frame.
The class Bullet do not need any loop. The constructor has to have parameters for the position (x, y). Further it needs on method which changes the position and one which draws the bullet:
class Bullet:
def __init__(self, x, y):
self.radius = 10
self.speed = 10
self.x = x
self.y = y
def update(self):
self.y -= self.speed#
def draw(self):
pygame.draw.circle(d, (255, 0, 0), (self.x, self.y), self.radius)
Use a list of bullets. Create a new bullet when space is pressed. Move the bullets (update) in every frame an remove a bullet if it is out of the window. Draw the remaining bullets in every frame:
bullets = []
# [...]
while run:
for event in pygame.event.get():
# [...]
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
bullets.append(Bullet(p.x+p.width//2, p.y))
# [...]
for b in bullets:
b.update()
if b.y < 0:
bullets.remove(b)
# [...]
for b in bullets:
b.draw()
Furthermore use pygame.key.get_pressed() use to get the state of the keys in every frame and to update the position of the player:
while run:
# [...]
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
p.move_left()
if keys[pygame.K_RIGHT]:
p.move_right()
Complete example:
import pygame, os
os.environ["SDL_VIDEO_CENTERED"] = "1"
pygame.init()
win = pygame.display
d = win.set_mode((1200, 600))
clock = pygame.time.Clock()
class Player:
def __init__(self, x, y, height, width):
self.x = x
self.y = y
self.height = height
self.width = width
self.speed = 2
def draw(self):
pygame.draw.rect(d, (0, 0, 0), (self.x, self.y, self.width, self.height))
def move_left(self):
self.x -= self.speed
def move_right(self):
self.x += self.speed
class Bullet:
def __init__(self, x, y):
self.radius = 10
self.speed = 10
self.x = x
self.y = y
def update(self):
self.y -= self.speed#
def draw(self):
pygame.draw.circle(d, (255, 0, 0), (self.x, self.y), self.radius)
bullets = []
p = Player(600, 500, 50, 30)
run = True
while run:
clock.tick(100)
# handel events
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
bullets.append(Bullet(p.x+p.width//2, p.y))
# update objects
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
p.move_left()
if keys[pygame.K_RIGHT]:
p.move_right()
for b in bullets:
b.update()
if b.y < 0:
bullets.remove(b)
# clear display
d.fill((98, 98, 98))
# draw scene
for b in bullets:
b.draw()
p.draw()
# update display
win.update()

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()

How to move my player sprite?

Here is my code. How can I move my class Player sprite? Would I add an x,y to my def __init__? like def __init__(self, x, y)? Thanks for the answers,
import pygame as pg
WIDTH = 800
HEIGHT = 600
CLOCK = pg.time.Clock()
FPS = 60
GREEN = (0, 255, 0)
LIGHTBLUE = (20, 130, 230)
BGCOLOR = LIGHTBLUE
class Player(pg.sprite.Sprite):
def __init__(self, x, y):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((50, 50))
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.rect.center = ((WIDTH / 2, HEIGHT / 2))
self.x = x
self.y = y
player = Player()
pg.init()
screen = pg.display.set_mode((WIDTH, HEIGHT))
pg.display.set_caption('The Moon Smiles Back')
running = True
while running:
for event in pg.event.get():
if event.type == pg.QUIT:
running = False
if event.type == pg.KEYDOWN:
if event.key == pg.K_ESCAPE:
running = False
all_sprites = pg.sprite.Group()
all_sprites.add(player)
all_sprites.update()
screen.fill(BGCOLOR)
all_sprites.draw(screen)
pg.display.flip()
CLOCK.tick(FPS)
pg.quit()
Add two attributes to the Player class to store the current velocity of the player. In the update method, add the velocities to the x and y attributes and then set the rect to the new position.
class Player(pg.sprite.Sprite):
def __init__(self, x, y):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((50, 50))
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.x = x
self.y = y
self.velocity_x = 0
self.velocity_y = 0
def update(self):
self.x += self.velocity_x
self.y += self.velocity_y
self.rect.center = (self.x, self.y)
To move the player to the right, set the player.velocity_x to the desired speed if the 'd' key is pressed (in this example), and back to 0 if the key is released. Do the same for the other directions.
if event.type == pg.KEYDOWN:
if event.key == pg.K_ESCAPE:
running = False
elif event.key == pg.K_d:
player.velocity_x = 3
elif event.type == pg.KEYUP:
if event.key == pg.K_d:
player.velocity_x = 0

Hexagon does not show

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

Categories