This question already has answers here:
How do I detect collision in pygame?
(5 answers)
How do I prevent the player from moving through the walls in a maze?
(3 answers)
Closed 9 months ago.
I am trying to learn the basics of pygame by making a simple pacman game with a friend, but I have been having trouble figuring out how to make walls and check collision with the pacman and the wall, and also stopping the movement through a wall.
(this is a 2 player pacman, ghost is arrow keys, and pacman is wasd)
This is main.py
import pygame
import random
import time
from Pacman import pacman
from Ghost import ghost
#colors
Yellow = (255,255,0)
Blackish_Blue = (20,0,70)
Red = (255,0,0)
P_B = (40,60,100)
clock = pygame.time.Clock()
#display
pygame.init()
pygame.display.set_caption(' Scuffed Pacman')
width, height = 640, 480
screen = pygame.display.set_mode((width, height))
pacman = pacman(screen)
ghost = ghost(screen)
font = pygame.font.Font('freesansbold.ttf', 32)
text = font.render('Game Over', True, Yellow)
textRect = text.get_rect()
textRect.center = (width / 2, height / 2)
run = True
while run == True:
pygame.time.delay(10)
clock.tick(60)
screen.fill(Blackish_Blue)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
color = (182,163,192)
#attempt to make wall and check collision
ghostspawn = pygame.Rect(0,0,60,40)
ghostspawn.center = (width / 2, (height / 2)-50)
pygame.draw.rect(screen, color, ghostspawn)
if ghostspawn.collidepoint(pacman.x, pacman.y):
print("collision detected")
pacman.draw(screen)
ghost.draw(screen)
ghost.update()
pacman.update()
distance = (((pacman.x - ghost.x)**2) + ((pacman.y - ghost.y)**2))**(1/2)
sumrad = pacman.radius + ghost.radius
if distance < sumrad:
while True:
screen.fill(P_B)
screen.blit(text, textRect)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
pygame.display.update()
pygame.display.update()
pygame.quit()
This is the code for pacman:
import pygame
Yellow = (255,255,0)
class pacman(pygame.sprite.Sprite):
def __init__(self, mainscreen):
super().__init__()
self.x = 320
self.y = 240
self.radius = 15
self.velocity = 2
self.origin = (self.x, self.y)
def draw(self, mainscreen):
pygame.draw.circle(mainscreen, Yellow, (self.x, self.y), self.radius)
def update(self):
self.movement()
self.origin = (self.x, self.y)
def movement(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_d] and self.velocity > 0 and self.x < 625:
self.x += self.velocity
if keys[pygame.K_a] and self.velocity > 0 and self.x > 15:
self.x -= self.velocity
if keys[pygame.K_w] and self.velocity > 0 and self.y > 15:
self.y -= self.velocity
if keys[pygame.K_s] and self.velocity > 0 and self.y < 465:
self.y += self.velocity
and this is the code for ghost:
import pygame
Red = (255,0,0)
class ghost(pygame.sprite.Sprite):
def __init__(self, mainscreen):
super().__init__()
self.x = 213
self.y = 240
self.radius = 15
self.velocity = 2
self.origin = (self.x, self.y)
def draw(self, mainscreen):
pygame.draw.circle(mainscreen, Red, (self.x, self.y), self.radius)
def update(self):
self.movement()
self.origin = (self.x, self.y)
def movement(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT] and self.velocity > 0 and self.x < 625:
self.x += self.velocity
if keys[pygame.K_LEFT] and self.velocity > 0 and self.x > 15:
self.x -= self.velocity
if keys[pygame.K_UP] and self.velocity > 0 and self.y > 15:
self.y -= self.velocity
if keys[pygame.K_DOWN] and self.velocity > 0 and self.y < 465:
self.y += self.velocity
this is my attempt at checking for wall collision, but I am unaware of how to stop pacman and the ghost from going through. the collision also only checks the middle of the circle.
ghostspawn = pygame.Rect(0,0,60,40)
ghostspawn.center = (width / 2, (height / 2)-50)
pygame.draw.rect(screen, color, ghostspawn)
if ghostspawn.collidepoint(pacman.x, pacman.y):
print("allowed")
here is how i detect collision between pacman and ghost, as it may be helpful for doing it with walls, but i don't know how.
distance = (((pacman.x - ghost.x)**2) + ((pacman.y - ghost.y)**2))**(1/2)
sumrad = pacman.radius + ghost.radius
ive looked at a few similar questions on here, but I can't quite grasp how it works.
So, if anyone could help, I'm having trouble with checking collision between a circle and rectangle, and also preventing the circle/pacman from moving through.
To check if a circle is colliding with a wall you just need to do 2 things
Get the distance between the circle and the wall
Then check if the distance is smaller or equal to the circles distance
Pretty much like this:
distance = abs(circle.x - wall.x) + abs(circle.y - wall.y)
if distance <= circle.radius: # abs() Makes the value in the brackets positive
circle.x = oldX
circle.y = oldY
To implement this I with your game would first add a self.oldX and a self.oldY in the self.__init__() in both of the pacman and ghost classes. And I would set them to 0 for now.
Then I would update the oldX and oldY in the movement function before I move the object, like this:
def movement(self):
keys = pygame.key.get_pressed()
self.oldX = self.x
self.oldY = self.y
if keys[pygame.K_d] and self.velocity > 0 and self.x < 625:
self.x += self.velocity
if keys[pygame.K_a] and self.velocity > 0 and self.x > 15:
self.x -= self.velocity
if keys[pygame.K_w] and self.velocity > 0 and self.y > 15:
self.y -= self.velocity
if keys[pygame.K_s] and self.velocity > 0 and self.y < 465:
self.y += self.velocity
Then I would have a list that containes every wall in the game and a list that containes every ghost in the game (That's if you want to have more than one ghost).
Then I would go in the main loop (The while loop that you have) and I would add this After calling the movement function of the ghosts and the pacman:
for wall in walls:
distance = abs(pacman.x - wall.x) + abs(pacman.y - wall.y)
if distance <= pacman.radius:
pacman.x = pacman.oldX
pacman.y = pacman.oldY
for ghost in ghosts:
distance = abs(ghost.x - wall.x) + abs(ghost.y - wall.y)
if distance <= ghost.radius:
ghost.x = ghost.oldX
ghost.y = ghost.oldY
and that should work, Thanks.
Related
This question already has an answer here:
Sometimes the ball doesn't bounce off the paddle in pong game
(1 answer)
Closed 8 months ago.
So here is the full code, but the problem is in the class Ball where my function move is. What happens when it executes is that the ball bounces and starts going lower and lower, just like real life. But when it hits the limit of how low it can go, the ball starts going under the limit.
I am very sorry for having taken your time.
from selectors import SelectorKey
from tkinter import Y
import pygame
pygame.init()
width, height = 1000, 600
Win = pygame.display.set_mode((width, height))
clock = pygame.time.Clock()
Acs = 0.5
class Ball():
def __init__(self):
self.y = 200
self.velocity = 10
self.bouncy = 1
def draw(self):
pygame.draw.circle(Win, (255, 0, 0), (500, self.y), 15)
def move(self):
self.velocity += Acs
self.y += self.velocity
print(self.velocity)
if self.y > 400:
self.velocity = -self.velocity + self.bouncy
if self.y <= 400:
self.velocity == 0
self.bouncy == 0
self.y == 400
def game():
ball = Ball()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
ball.move()
Win.fill((255, 255, 255))
pygame.draw.line(Win, (0, 0, 0), (0, 400), (1000, 400), 10)
ball.draw()
clock.tick(60)
pygame.display.update()
game()
pygame.quit()
where I have a problem is here:
def move(self):
self.velocity += Acs
self.y += self.velocity
print(self.velocity)
if self.y > 400:
self.velocity = -self.velocity + self.bouncy
if self.y <= 400:
self.velocity == 0
self.bouncy == 0
self.y == 400
The problem with bouncing balls (and every non-linear physics simulation where you have very drastic changes) is that your simulation might put you below the limit in a single time step, so you have to make sure that you enforce the limit. A simple way to fix that for a game is to force the y position when you hit the floor. Change your move method to this and it works (note that the if self.y <= 400: branch didn't do anything, so I removed it).
def move(self):
self.velocity += Acs
self.y += self.velocity
if self.y > 400:
self.velocity = -self.velocity + self.bouncy
self.y = 400 # Ensure the limits
For a slightly more realistic bouncing effect, you can use your self.bouncy attribute as an actual coefficient of restitution and change slightly the formula for the bounce. 5% of loss every bounce gave a reasonably good result.
class Ball():
def __init__(self):
self.y = 200
self.velocity = 10
self.bouncy = 0.05 # Now a coefficient of restitution
def draw(self):
pygame.draw.circle(Win, (255, 0, 0), (500, self.y), 15)
def move(self):
self.velocity += Acs
self.y += self.velocity
if self.y > 400: # Note that the loss of velocity is a function of the previous velocity
self.velocity = -self.velocity + self.bouncy*self.velocity
self.y = 400 # Ensure the limits
This question already has an answer here:
Sometimes the ball doesn't bounce off the paddle in pong game
(1 answer)
Closed 1 year ago.
I am currently trying to create a pong game but for some reason, the ball would not bounce off of the rectangles and I am not sure where I have made a mistake even though I followed a video about rectangle collision online. Please let me know where I made a mistake and how I can improve my code. Thanks!
import pygame, sys, random, time
from pygame.time import Clock
pygame.init()
#colours
black = ( 0, 0, 0)
white = ( 255, 255, 255)
green = ( 0, 255, 0)
red = ( 255, 0, 0)
# Display
screen_width = 1000
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("2-player Pong")
# Rectangles
class Rectangle():
def __init__(self, screen, x):
self.screen = screen
self.screen_rect= screen.get_rect()
self.x = x
self.y = 250
self.width = 30
self.height = 100
self.rect = pygame.Rect(self.x, self.y, self.width, self.height)
self.colour = black
self.velocity = 5
def draw_rectangle(self):
pygame.draw.rect(self.screen, self.colour, self.rect)
rect1 = Rectangle(screen, 50)
rect2 = Rectangle(screen, 920)
class Ball():
def __init__(self, colour):
self.screen = screen
self.colour = colour
self.width = 20
self.height = 20
self.x = screen_width//2 - 25
self.y = screen_height//2 - 25
self.rect = pygame.Rect(self.x, self.y, self.width, self.height)
self.possible_velocities_x = [-4, 4]
self.possible_velocities_y = [-2, 2]
self.velocity = [random.choice(self.possible_velocities_x), random.choice(self.possible_velocities_y)]
def draw_ball(self):
pygame.draw.rect(self.screen, self.colour, self.rect)
def move_ball(self):
global rect1, rect2
self.rect.x += self.velocity[0]
self.rect.y += self.velocity[1]
# Collision with Screen
if self.rect.top <= 10 or self.rect.bottom >= screen_height - 10:
self.velocity[1] *= -1
# Collision with Rectangles
if self.rect.colliderect(rect1) or self.rect.colliderect(rect2):
if self.rect.left - rect1.rect.right == 0:
self.possible_velocities_x *= -1
if self.rect.right - rect2.rect.left == 0:
self.possible_velocities_x *= -1
clock = pygame.time.Clock()
ball = Ball(white)
pong = True
while pong:
pygame.time.delay(10)
clock.tick(100)
# Watch for keyboard and mouse events.
for event in pygame.event.get():
if event.type == pygame.QUIT:
pong = False
keys = pygame.key.get_pressed()
if keys[pygame.K_UP] and rect2.rect.y >= 0:
rect2.rect.y -= rect2.velocity
if keys[pygame.K_DOWN] and rect2.rect.y <= 600 - rect2.rect.height:
rect2.rect.y += rect2.velocity
if keys[pygame.K_w] and rect1.rect.y >= 0:
rect1.rect.y -= rect1.velocity
if keys[pygame.K_s] and rect1.rect.y <= 600 - rect1.rect.height:
rect1.rect.y += rect1.velocity
screen.fill(green)
rect1.draw_rectangle()
rect2.draw_rectangle()
ball.draw_ball()
ball.move_ball()
# pygame.draw.rect(screen, black, (rect_x2, rect_y2, rect_width2, rect_height2))
pygame.display.update() # Make the most recently drawn screen visible.
pygame.quit()
You must change self.velocity[0] when the ball touches the paddle. Since the movement of the ball is more than 1 pixel per frame, the ball does not exactly touch the paddle. This mans the condition self.rect.left - rect1.rect.right == 0 and self.rect.right - rect2.rect.left == 0 will not be fulfilled. If the movement in x direction is negative, the new movement needs to be positive (abs(self.velocity[0])). If the movement in x direction is positive, the new movement needs to be negative (-abs(self.velocity[0])):
class Ball():
# [...]
def move_ball(self):
self.rect.x += self.velocity[0]
self.rect.y += self.velocity[1]
# Collision with Screen
if self.rect.top <= 10 or self.rect.bottom >= screen_height - 10:
self.velocity[1] *= -1
# Collision with Rectangles
if self.rect.colliderect(rect1) or self.rect.colliderect(rect2):
if self.velocity[0] < 0:
self.velocity[0] = abs(self.velocity[0])
else:
self.velocity[0] = -abs(self.velocity[0])
See also Sometimes the ball doesn't bounce off the paddle in pong game
Apologies for asking so many questions recently. I'm just starting to get into pygame.
With my previous questions I don't think I've been wording it properly for what I am trying to do.
Here is a quick picture I did to try demonstrate
This is a single background image or map that I would like the player to move across. The red X is just a starting place for the character.
I'm try to make it so when I move the player the background will also follow as if the player is moving through the map. I've already limited the player from not being able to go off the borders of the actual screen. Just having a bit of trouble now trying to make it so the single image will move along the player and if the player reaches the end of the map picture movement stops. I have seen people use scrolling and duplicating the image when the player moves. I just want to see it to the single image that the player will move across. I don't want to worry about collisions just be able to get the movement working.
This is the code I am currently using:
from pygame.locals import *
from math import sin
pygame.display.set_caption("TEST")
clock = pygame.time.Clock()
time_passed = 0
class Player():
def __init__(self,x,y):
self.Image = pygame.image.load("myAvatar.png").convert()
self.x = 200
self.y = 200
def getX(self):
return self.rect.x
def getY(self):
return self.rect.y
def handle_keys(self,screenHeight,screenWidth):
key = pygame.key.get_pressed()
dist = 2
if key[K_LEFT] and self.x > 0:
self.x -= 500 * time_passed
if key[K_RIGHT] and self.x < screenWidth -20:
self.x += 500 * time_passed
if key[K_UP] and self.y > 0:
self.y -= 500 * time_passed
if key[K_DOWN] and self.y < screenHeight -20:
self.y += 500 * time_passed
def draw(self, game_window):
self.Image = pygame.transform.scale(self.Image,(20,20))
game_window.blit(self.Image, (int(self.x), int(self.y)))
class Map():
def __init__(self):
self.Image = pygame.image.load("test2.png").convert()
self.rect = self.Image.get_rect()
self.x = 0
self.y = 0
def draw(self, game_window,screenHeight,screenWidth):
self.x = min(max(self.x, player.x - 2 * screenWidth / 2), player.x - screenWidth / 2)
self.y = min(max(self.y, player.y -2 * screenHeight / 2), player.y - screenHeight / 2)
game_window.blit(self.Image,(-self.x,-self.y))
class Enemy():
def __init__ (self,x,y):
self.Image = pygame.image.load("WC.jpg").convert()
self.rect = self.Image.get_rect(topleft = (x,y))
def draw(self, game_window):
self.Image = pygame.transform.scale(self.Image,(20,20))
game_window.blit(self.Image, (self.rect.x, self.rect.y))
pygame.init()
clock = pygame.time.Clock()
screenWidth = 400
screenHeight = 400
game_window = pygame.display.set_mode((screenWidth,screenHeight))
player = Player(200,200)
map = Map()
enemy = Enemy(250,250)
leave = False
while not leave:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
running = False
player.handle_keys(screenHeight,screenWidth)
game_window.fill((0,0,0))
map.draw(game_window,screenHeight,screenWidth)
#enemy.draw(game_window)
player.draw(game_window)
pygame.display.update()
pygame.display.flip()
time_passed = clock.tick() / 1000
pygame.quit()
quit()
Thanks
Shay
The player's movement depends on the size of the map. The x and y attributes of the "player" store the position on the map and are limited to the size of the map (map_size). The player is always drawn in the center of the screen, except it is near the boarders of the map:
class Player():
def __init__(self, x, y):
self.Image = pygame.image.load("myAvatar.png").convert()
self.x = 200
self.y = 200
def handle_keys(self, map_size):
key = pygame.key.get_pressed()
self.x += (key[K_RIGHT] - key[K_LEFT]) * 500 * time_passed
self.y += (key[K_DOWN] - key[K_UP]) * 500 * time_passed
self.x = max(0, min(map_size[0]-20, self.x))
self.y = max(0, min(map_size[1]-20, self.y))
def draw(self, game_window, map_size):
window_size = game_window.get_size()
center = window_size[0] // 2, window_size[0] // 2
pos = [self.x, self.y]
for i in range(2):
if center[i] < pos[i] <= map_size[i]-center[i]:
pos[i] = center[i]
elif pos[i] > map_size[i] - center[i]:
pos[i] = window_size[i] - map_size[i] + pos[i]
game_window.blit(self.Image, (int(pos[0]), int(pos[1])))
The player's position on the map is centered in the window:
class Map():
def __init__(self):
self.Image = pygame.image.load("test2.png").convert()
def draw(self, game_window):
window_size = game_window.get_size()
map_size = self.Image.get_size()
x = max(0, min(map_size[0] - window_size[0], player.x - 200))
y = max(0, min(map_size[1] - window_size[1], player.y - 200))
game_window.blit(self.Image, (-x, -y))
Application loop:
leave = False
while not leave:
for event in pygame.event.get():
if event.type == pygame.QUIT:
leave = True
player.handle_keys(map.Image.get_size())
game_window.fill((0,0,0))
map.draw(game_window)
#enemy.draw(game_window)
player.draw(game_window, map.Image.get_size())
pygame.display.update()
pygame.display.flip()
time_passed = clock.tick() / 1000
pygame.quit()
I am making a simple variation of space invaders using pygame. Here is some working code:
import pygame, random, time, tkinter
pygame.init()
def main():
X = 672
Y = 500
win = pygame.display.set_mode((X,Y))
pygame.display.set_caption('Space Invaders')
class player(object):
def __init__(self, x, y, width, height):
self.x = x
self.y = y
self.width = width
self.height = height
self.lives = 3
self.vel = 5
self.points = 0
self.explosionYN = False
self.explosionCount = 0
self.highScore = int(text)
def explosion(self, win):
if self.explosionYN:
win.blit(explosion[self.explosionCount], (self.x-20, self.y-30, 100, 100))
self.explosionCount += 1
if not self.explosionYN:
self.explosionCount = 0
if self.explosionCount + 1 > 6:
self.explosionYN = False
self.explosionCount = 0
def move(self, win):
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and self.x > -1:
self.x -= self.vel
if keys[pygame.K_RIGHT] and self.x < 623:
self.x += self.vel
if keys[pygame.K_q]:
if self.x >= 623:
self.x = 0
if self.x < 0:
self.x = 623
class invader(object):
def __init__(self, x, y, width, height):
self.x = x
self.y = y
self.width = width
self.height = height
self.vel = 1
def reset(self, win):
self.y = 0
self.x = random.randint(5, (X-35))
class bullet(object):
def __init__(self, x, y, width, height):
self.x = x
self.y = y
self.width = width
self.height = height
self.vel = 0
def shoot(self, win):
laser.play(0)
self.x = ship.x + 22
self.y = ship.y
self.vel = 15
def reset(self, win):
self.vel = 0
self.y = 510
ship = player(X//2 - (0.5*52), 435, 52, 52)
alien = invader(random.randint(0,707),0,31,25)
bullet = bullet(750, 510, 5, 7)
while run:
pygame.time.delay(25)
alien.y += alien.vel
bullet.y -= bullet.vel
if alien.y > 500:
ship.explosionYN = True
ship.explosion(win)
loseLife.play(0)
if ship.explosionCount+ 1 >= 6:
win.fill((0,0,0))
pause()
ship.lives -= 1
alien.reset(win)
elif ship.lives <= 1:
test()
if bullet.y <= 0:
bullet.reset(win)
alien1 = pygame.draw.rect(win, (0,0,0), (alien.x,alien.y,31,25))
bullet1 = pygame.draw.rect(win, (0,100,255), (bullet.x, bullet.y, bullet.width, bullet.height))
if pygame.Rect.colliderect(alien1, bullet1):
ship.points += 1
if ship.highScore < ship.points:
ship.highScore += 1
bullet.reset(win)
kill.play(0)
alien.y = 0
alien.reset(win)
alien.vel += 0.5
ship.vel += 0.25
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
keys = pygame.key.get_pressed()
ship.move(win)
if keys[pygame.K_SPACE] or keys[pygame.K_UP]:
bullet.shoot(win)
if keys[pygame.K_p]:
pause()
drawGame()
main()
I have omitted some code that I don't think is relevant
The problem is that only one bullet can be displayed on screen at a time.
So I tried this instead.
if keys[pygame.K_SPACE] or keys[pygame.K_UP]:
bullet1 = pygame.draw.rect(win, (#stuff))
bullet.shoot(win)
But now the bullet doesn't show at all.
Literally nothing happens.
I have looked at some other posts but as I am new to pygame I can't make head or tail of them.(Multiple Bullets pygame)
What is an easy and effiecient way to be able show multiple bullets on pygame?
thanks.
The typical way that this is done is by creating a list of bullets.
bullets = []
Then when you fire a bullet you add it to the list
bullets.append(Bullet(750, 510, 5, 7))
And inside your while loop, you will update and redraw each bullet in turn using a for loop to iterate over each bullet
for bullet in bullets:
bullet.y -= bullet.vel # Move Bullet
# Draw bullet
# Check for collision with player/enemy
This obviously isn't a complete code listing but hopefully it is enough to get you started.
You'll also end up having to create a list of enemies too if you want to create a space invaders clone.
You may find the recently released book "Code the Classics" from the Raspberry Pi Foundation helpful as it explains how to create some classic games using Pygame. It's a free download (or you can buy the hardcopy)
Edit: Consider following the Python style guide PEP-8 and renaming your classes to be title case. For example
class bullet():
should be
class Bullet():
This will help with any confusion between the variable bullet and the class of the same name.
Apologies for asking so many questions recently. I'm just starting to get into pygame.
With my previous questions I don't think I've been wording it properly for what I am trying to do.
Here is a quick picture I did to try demonstrate
This is a single background image or map that I would like the player to move across. The red X is just a starting place for the character.
I'm try to make it so when I move the player the background will also follow as if the player is moving through the map. I've already limited the player from not being able to go off the borders of the actual screen. Just having a bit of trouble now trying to make it so the single image will move along the player and if the player reaches the end of the map picture movement stops. I have seen people use scrolling and duplicating the image when the player moves. I just want to see it to the single image that the player will move across. I don't want to worry about collisions just be able to get the movement working.
This is the code I am currently using:
from pygame.locals import *
from math import sin
pygame.display.set_caption("TEST")
clock = pygame.time.Clock()
time_passed = 0
class Player():
def __init__(self,x,y):
self.Image = pygame.image.load("myAvatar.png").convert()
self.x = 200
self.y = 200
def getX(self):
return self.rect.x
def getY(self):
return self.rect.y
def handle_keys(self,screenHeight,screenWidth):
key = pygame.key.get_pressed()
dist = 2
if key[K_LEFT] and self.x > 0:
self.x -= 500 * time_passed
if key[K_RIGHT] and self.x < screenWidth -20:
self.x += 500 * time_passed
if key[K_UP] and self.y > 0:
self.y -= 500 * time_passed
if key[K_DOWN] and self.y < screenHeight -20:
self.y += 500 * time_passed
def draw(self, game_window):
self.Image = pygame.transform.scale(self.Image,(20,20))
game_window.blit(self.Image, (int(self.x), int(self.y)))
class Map():
def __init__(self):
self.Image = pygame.image.load("test2.png").convert()
self.rect = self.Image.get_rect()
self.x = 0
self.y = 0
def draw(self, game_window,screenHeight,screenWidth):
self.x = min(max(self.x, player.x - 2 * screenWidth / 2), player.x - screenWidth / 2)
self.y = min(max(self.y, player.y -2 * screenHeight / 2), player.y - screenHeight / 2)
game_window.blit(self.Image,(-self.x,-self.y))
class Enemy():
def __init__ (self,x,y):
self.Image = pygame.image.load("WC.jpg").convert()
self.rect = self.Image.get_rect(topleft = (x,y))
def draw(self, game_window):
self.Image = pygame.transform.scale(self.Image,(20,20))
game_window.blit(self.Image, (self.rect.x, self.rect.y))
pygame.init()
clock = pygame.time.Clock()
screenWidth = 400
screenHeight = 400
game_window = pygame.display.set_mode((screenWidth,screenHeight))
player = Player(200,200)
map = Map()
enemy = Enemy(250,250)
leave = False
while not leave:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
running = False
player.handle_keys(screenHeight,screenWidth)
game_window.fill((0,0,0))
map.draw(game_window,screenHeight,screenWidth)
#enemy.draw(game_window)
player.draw(game_window)
pygame.display.update()
pygame.display.flip()
time_passed = clock.tick() / 1000
pygame.quit()
quit()
Thanks
Shay
The player's movement depends on the size of the map. The x and y attributes of the "player" store the position on the map and are limited to the size of the map (map_size). The player is always drawn in the center of the screen, except it is near the boarders of the map:
class Player():
def __init__(self, x, y):
self.Image = pygame.image.load("myAvatar.png").convert()
self.x = 200
self.y = 200
def handle_keys(self, map_size):
key = pygame.key.get_pressed()
self.x += (key[K_RIGHT] - key[K_LEFT]) * 500 * time_passed
self.y += (key[K_DOWN] - key[K_UP]) * 500 * time_passed
self.x = max(0, min(map_size[0]-20, self.x))
self.y = max(0, min(map_size[1]-20, self.y))
def draw(self, game_window, map_size):
window_size = game_window.get_size()
center = window_size[0] // 2, window_size[0] // 2
pos = [self.x, self.y]
for i in range(2):
if center[i] < pos[i] <= map_size[i]-center[i]:
pos[i] = center[i]
elif pos[i] > map_size[i] - center[i]:
pos[i] = window_size[i] - map_size[i] + pos[i]
game_window.blit(self.Image, (int(pos[0]), int(pos[1])))
The player's position on the map is centered in the window:
class Map():
def __init__(self):
self.Image = pygame.image.load("test2.png").convert()
def draw(self, game_window):
window_size = game_window.get_size()
map_size = self.Image.get_size()
x = max(0, min(map_size[0] - window_size[0], player.x - 200))
y = max(0, min(map_size[1] - window_size[1], player.y - 200))
game_window.blit(self.Image, (-x, -y))
Application loop:
leave = False
while not leave:
for event in pygame.event.get():
if event.type == pygame.QUIT:
leave = True
player.handle_keys(map.Image.get_size())
game_window.fill((0,0,0))
map.draw(game_window)
#enemy.draw(game_window)
player.draw(game_window, map.Image.get_size())
pygame.display.update()
pygame.display.flip()
time_passed = clock.tick() / 1000
pygame.quit()