How to create a variable with code (Python) - python

So I have this platformer game. I need a variable creator. It's hard to explain. Here's the code...
import pygame,time,random,sys
pygame.display.set_caption('My Platformer V1.0')
x = 10
y = 30
import os
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (x,y)
GREEN = (0,255,0)
WHITE =(0,0,0)
BLACK = (0, 0, 0)
BLUE = (0, 0, 255)
LIGHTBLUE = (60,60,240)
LIGHTBROWN = (255, 236, 139)
RED = (255, 0, 0)
YELLOW = (255,255,0)
DARKRED = (102,0,0)
GRAY = (160,160,160)
WINDOWWIDTH = 1200
WINDOWHEIGHT = 700
mainClock = pygame.time.Clock()
from pygame.locals import *
pygame.init()
PlayerRect = pygame.Rect(0,0,50,80)
global PlayerX
global PlayerY
PlayerX = 0
PlayerY = 0
moveRight = False
moveLeft = False
moveUp = False
moveDown = False
gravity = False
Jump = False
JumpTime = 0
global PPX
global PPY
PPX = PlayerX
PPY = PlayerY
screen = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), 0, 32)
# Define Functions ---------------------------------------- #
def platform_spawnandcheck(x,y,sx,sy):
Rect2 = pygame.Rect(x,y,sx,sy)
pygame.draw.rect(screen,WHITE,Rect2)
pygame.draw.rect(screen,GREEN,PlayerRect)
pygame.display.update()
y2 = y
y2 += 80
global PlayerY
if PlayerY < y2:
if PlayerRect.colliderect(Rect2):
global PPX
global PlayerY
PlayerY = PPY
if PlayerY > y2:
if PlayerRect.colliderect(Rect2):
global PPX
PlayerX = PPX
while True:
# Make Past Coordinance ------------------------------- #
PPX = PlayerX
PPY = PlayerY
# Jump ------------------------------------------------ #
if Jump == True:
JumpTime += 1
PlayerY -= 12
if JumpTime == 30:
Jump = False
JumpTime = 0
# Gravity --------------------------------------------- #
gravity = True
# Movement -------------------------------------------- #
if moveRight == True:
PlayerX += 5
if moveLeft == True:
PlayerX -= 5
if PlayerY > 620:
gravity = False
if moveUp == True:
PlayerY -= 3
if gravity == False:
Jump = True
if gravity == True:
PlayerY += 5
# Reload the player Rect ------------------------------ #
PlayerRect = pygame.Rect(PlayerX,PlayerY,50,80)
# Check for pressed keys ------------------------------ #
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == ord('d'):
moveRight = True
if event.key == K_SPACE:
moveUp = True
if event.key == ord('a'):
moveLeft = True
if event.type == KEYUP:
if event.key == ord('d'):
moveRight = False
if event.key == K_SPACE:
moveUp = False
if event.key == ord('a'):
moveLeft = False
# Update ---------------------------------------------- #
screen.fill(LIGHTBLUE)
platform_spawnandcheck(500,650,100,20)
pygame.draw.rect(screen,GREEN,PlayerRect)
pygame.display.update()
mainClock.tick(60)
So if you look at the code...
You will see that I need a variable generator to make new variables for individual platforms. (I'm talking about the function "platform_spawnandcheck".) (The platforms are for pygame.)
def platform_spawnandcheck(x,y,sx,sy):
Rect2 = pygame.Rect(x,y,sx,sy)
pygame.draw.rect(screen,WHITE,Rect2)
pygame.draw.rect(screen,GREEN,PlayerRect)
pygame.display.update()
y2 = y
y2 += 80
global PlayerY
if PlayerY < y2:
if PlayerRect.colliderect(Rect2):
global PPX
global PlayerY
PlayerY = PPY
if PlayerY > y2:
if PlayerRect.colliderect(Rect2):
global PPX
PlayerX = PPX
Just answer the part about making variables. I want something to make variables for me like have it make var1 var2 var3 var4 and so on.
I still need ANSWERS.

A - if it is hard to explain, you are probably missing some clarity that is necessary for coding
B- familiarize yourself with "dict"
move = {"up":False, "down":True}
is what you want.
you can then add values
move["jump"]=True

So you need to create variables using logic rather than making a direct assignment. That is what I get from your question. So rather than this,
a = 10
you want to do
if some logic:
make_var(10) # somehow returns (a,10) in bizaro python
Although, this is one way to make a variable assignment, that is not the right way. What vish is trying to tell you is that you can make variables by creating a python dict and making an assignment inside the dict as
made_vars = {}
if some logic:
made_vars[a] = 10
print made_vars[a] # should print 10
So you get your assignment done. However instead of names var1, var2 etc, you would have the variable names as made_var[var1], made_var[var2] etc.
I was searching for a better explanation online, and I came up with this link.

You should create a class for the platforms that gets initialized with some random position.
The __init__ method of a class is the "generator" for that class, also known as a constructor. Construct instances of the class with Platform(), and the __init__ method is called and returns a new Platform object.
class Platform:
def __init__(self):
self.x = random.randint(0, WINDOWWIDTH)
self.y = random.randint(0, WINDOWHEIGHT)
self.sx = 100
self.sy = 20
# creating platforms
platforms = []
for i in xrange(20):
platforms.append(Platform())
# accessing the coordinates of the platforms
for platform in platforms:
print platform.x, platform.y, platform.sx, platform.sy
# passing the platforms into your function
for platform in platforms:
platform_spawnandcheck(platform.x, platform.y, platform.sx, platform.sy)

Related

Issue with Collision Detection in Pygame for simple 2D Platformer

This is my first post so please let me know if I should alter anything.
I am attempting to create a simple test 2D platformer, this is the first pygame project I've undertaken without a tutorial. The issue I am encountering is due to this can_jump variable. I am using this variable to stop the player from being able to jump when not on a platform or the bottom of the screen. I had attempted other methods but this is where I have ended up. I feel I've gotten so close.
The issue at the moment appears to be that the variable self.can_jump1 continuously swaps between True and False in the platform loop (at exactly 3 Falses for every True I have noticed) when standing on a platform, I have isolated it to the commented section in collision_check(). I don't know why this happens, and as far as I can tell the rest of the code works as I want it.
I would be happy to provide any extra information/clarification if need be.
Here's my code:
import pygame, sys, random
#---Classes----------------------------------------#
class Block(pygame.sprite.Sprite): #inherited by rest of classes
def __init__(self,path,x_pos,y_pos,size_x,size_y):
super().__init__()
self.image = pygame.transform.scale(pygame.image.load(path).convert_alpha(),(size_x,size_y))
self.rect = self.image.get_rect(center = (x_pos,y_pos))
class PlatformRect(pygame.sprite.Sprite):
def __init__(self,x_pos,y_pos,size_x,size_y,colour,players):
super().__init__()
self.center_x = x_pos
self.center_y = y_pos
self.size_x = size_x
self.size_y = size_y
self.colour = colour
self.players = players
self.can_jump1 = None
self.image = pygame.Surface((self.size_x,self.size_y))
self.image.fill(self.colour)
self.rect = self.image.get_rect(center = (self.center_x,self.center_y))
def collision_check(self):
if pygame.sprite.spritecollide(self,self.players,False):
collision_paddle = pygame.sprite.spritecollide(self,self.players,False)[0].rect
if abs(self.rect.top - collision_paddle.bottom) < 10:
collision_paddle.bottom = self.rect.top
player.movement_y = 0
self.can_jump1 = True
else: #error isolated to here,consistently fluctuates between True and False, not sure why
self.can_jump1 = False
print(self.can_jump1) #if standing on platform should only produce True, everywhere else produce False
def can_jump_check(self):
return self.can_jump1
def update(self):
self.collision_check()
class Player(Block):
def __init__(self,path,x_pos,y_pos,size_x,size_y,speed_x,acceleration_y):
super().__init__(path,x_pos,y_pos,size_x,size_y)
self.size_x = size_x
self.size_y = size_y
self.speed_x = speed_x
self.acceleration_y = acceleration_y
self.movement_x = 0
self.movement_y = 0
def screen_constrain(self):
if self.rect.bottom >= sresy:
self.rect.bottom = sresy
if self.rect.left <= 0:
self.rect.left = 0
if self.rect.right >= sresx:
self.rect.right = sresx
def update(self):
if abs(self.movement_y) <= 9:
self.movement_y += GRAVITY
self.rect.centery += self.movement_y
self.rect.centerx += self.movement_x
self.screen_constrain()
class GameManager:
def __init__(self,player_group,platform_group):
self.player_group = player_group
self.platform_group = platform_group
self.can_jump = True
def run_game(self):
#---drawing---#
self.player_group.draw(screen)
self.platform_group.draw(screen)
#---updating---#
self.player_group.update()
self.platform_group.update()
def game_checking(self):
#---checking---#
for sprite_platform in self.platform_group.sprites():
if not sprite_platform.can_jump_check() == True:
self.can_jump = False
else:
self.can_jump = True
return self.can_jump
#---Setup------------------------------------------#
#---constants-----#
global GRAVITY
GRAVITY = 0.25
#---Gamevariables-----#
can_jump = True
#---colour---#
bg_colour = (50,50,50)
white_colour = (255,255,255)
black_colour = (0,0,0)
#---res---#
resx = 900
resy = 675
sresx = resx - 50
sresy = resy - 50
#---start window-----#
clock = pygame.time.Clock()
screendisplay = pygame.display.set_mode((resx,resy))
screendisplay.fill(bg_colour)
pygame.display.set_caption("PlatformerGame1 started 09/02/2021")
screen = pygame.Surface((sresx,sresy))
screen.fill(white_colour)
#---startgame-----#
player = Player("assets\\pics\\TestPlayerFigure1_256512.png",100,100,32,64,10,30)
player_group = pygame.sprite.GroupSingle()
player_group.add(player)
platform1 = PlatformRect(100,550,100,10,black_colour,player_group)
platform_group = pygame.sprite.Group()
platform_group.add(platform1)
game_manager = GameManager(player_group,platform_group)
#---Loop--------------------------------------------#
while True:
#---events-----#
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
if event.key == pygame.K_SPACE:
if can_jump == True:
player.movement_y = 0
player.movement_y -= player.acceleration_y * GRAVITY
if event.key == pygame.K_a:
player.movement_x -= player.speed_x
if event.key == pygame.K_d:
player.movement_x += player.speed_x
if event.type == pygame.KEYUP:
if event.key == pygame.K_SPACE:
if player.movement_y < 0:
player.movement_y = 0
if event.key == pygame.K_a:
player.movement_x += player.speed_x
if event.key == pygame.K_d:
player.movement_x -= player.speed_x
#---background---#
screendisplay.blit(screen,(25,25))
screen.fill(white_colour)
#---running---#
game_manager.run_game()
if not game_manager.game_checking() == True and player.rect.bottom < sresy:
can_jump = False
else:
can_jump = True
#print(can_jump)
#---updating-----#
pygame.display.update()
clock.tick(60)
When the player is standing on the platform, the player does not collide with the platform and self.can_jump1 is set False. Test if the player is on the platform when the player does not collide with the platform:
self.can_jump1 = False
self.can_jump1 = self.rect.top == self.players.sprites()[0].rect.bottom
Method collision_check:
class PlatformRect(pygame.sprite.Sprite):
# [...]
def collision_check(self):
collide_list = pygame.sprite.spritecollide(self,self.players,False)
if collide_list:
collision_paddle = collide_list[0].rect
if abs(self.rect.top - collision_paddle.bottom) < 10:
collision_paddle.bottom = self.rect.top
player.movement_y = 0
self.can_jump1 = True
else:
self.can_jump1 = self.rect.top == self.players.sprites()[0].rect.bottom
GameManager.game_checking needs to check if the plyer collides with any platform:
class GameManager:
# [...]
def game_checking(self):
#---checking---#
self.can_jump = False
for sprite_platform in self.platform_group.sprites():
if sprite_platform.can_jump_check() == True:
self.can_jump = True
return self.can_jump
This can be simplified with the any function:
class PlatformRect(pygame.sprite.Sprite):
# [...]
def game_checking(self):
#---checking---#
self.can_jump = any(p.can_jump_check() for p in self.platform_group)
return self.can_jump

How do I use Images in pygame for collision detection [duplicate]

This question already has answers here:
How to detect collisions between two rectangular objects or images in pygame
(1 answer)
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)
How do I detect collision in pygame?
(5 answers)
Closed 2 years ago.
import pygame
import os
pygame.init()
# Images
bgImg = pygame.image.load("Images/background.png")
playerImgRight = (pygame.image.load("Images/playerRight.png"))
playerImgLeft = pygame.image.load("Images/playerLeft.png")
playerImgBack = pygame.image.load("Images/playerBack.png")
chestClosed = pygame.transform.scale(pygame.image.load("Images/chestsClosed.png"), (30, 40))
chestOpened = pygame.transform.scale(pygame.image.load("Images/chestOpen.png"), (30, 40))
currentPlayerImg = playerImgBack
screen = pygame.display.set_mode((800, 800))
pygame.display.set_caption("Richmonia")
pygame.display.set_icon(currentPlayerImg)
clock = pygame.time.Clock()
playerX = 380
playerY = 380
playerXSpeed = 0
playerYSpeed = 0
Chest Class
I want but the collision detection in the chest update function
class Chest:
def __init__(self, x, y, openImage, closeImage, playerX, playerY):
self.x = x
self.y = y
self.openImage = openImage
self.closeImage = closeImage
self.currentImage = self.closeImage
self.playerX = playerX
self.playerY = playerY
def update(self):
print("Placeholder")
def show(self):
screen.blit(self.currentImage, (self.x, self.y))
chestOne = Chest(100, 100, chestOpened, chestClosed, playerX, playerY)
running = True
while running:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
currentPlayerImg = playerImgBack
playerYSpeed = -5
if event.key == pygame.K_DOWN:
currentPlayerImg = playerImgBack
playerYSpeed = 5
if event.key == pygame.K_LEFT:
currentPlayerImg = playerImgLeft
playerXSpeed = -5
if event.key == pygame.K_RIGHT:
currentPlayerImg = playerImgRight
playerXSpeed = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
playerYSpeed = 0
if event.key == pygame.K_DOWN:
playerYSpeed = 0
if event.key == pygame.K_LEFT:
playerXSpeed = 0
if event.key == pygame.K_RIGHT:
playerXSpeed = 0
if playerY <= 0:
playerY = 0
if playerY >= 740:
playerY = 740
if playerX <= 0:
playerX = 0
if playerX >= 760:
playerX = 760
playerX += playerXSpeed
playerY += playerYSpeed
screen.blit(bgImg, (0, 0))
chestOne.show()
chestOne.update()
screen.blit(currentPlayerImg, (playerX, playerY))
pygame.display.update()
pygame.quit()
quit()
I know there is a way with sprites but I want to know if there is a way to do it with just the images.
Also bonus question how to I get the fps.
Use a pygame.Rect object and colliderect() to find a collision between a rectangle and an object.
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. The position of the rectangle can be specified by a keyword argument:
running = True
while running:
# [...]
player_rect = currentPlayerImg.get_rect(topleft = (playerX, playerY))
chestOne_rect = chestOne.currentImage.get_rect(topleft = (self.x, self.y))
if player_rect .colliderect(chestOne_rect):
print("hit")
# [...]
The method tick() of a pygame.time.Clock object, delays the game in that way, that every iteration of the loop consumes the same period of time.
So in your case the frames per second are 60:
while running:
clock.tick(60)
pygame.time.Clock.tick returns the number of milliseconds passed since the previous call. If you call it in the application loop, then this is the number of milliseconds passed since the last frame.
while run:
ms_since_last_frame = clock.tick(60)

how to make bullet come out according to the object

i am still learning on how to use pygame and i just created a space invader inspired game. but one issue that i have right now is that the bullet does not come out accordingly to my object's location. instead it only comes out from the bottom of the screen. i want my bullet to come out accordingly to my object no matter if its moving up, down, right or left. thank you in advance!!
import pygame
import random
import math
#intialize the pygame
pygame.init()
#create the screen
screen = pygame.display.set_mode((700,583))
#Caption and icon
pygame.display.set_caption("Yoshi & Fruits")
icon = pygame.image.load("Yoshi_icon.png")
pygame.display.set_icon(icon)
#Player
playerImg = pygame.image.load("YoshiMario.png")
playerX = 370
playerY = 480
playerX_change = 0
playerY_change = 0
#Enemy
enemyImg = pygame.image.load('msh1.png')
enemyX = random.randint(0,735)
enemyY = random.randint(50,150)
enemyX_change = 2
enemyY_change = 30
#Knife
# ready - you cant see the knife on the screen
# fire - the knife is currently moving
knifeImg = pygame.image.load('diamondsword3.png')
knifeX = 0
knifeY = 480
knifeX_change = 0
knifeY_change = 10
knife_state = "ready"
score = 0
def player(x,y):
screen.blit(playerImg, (x, y))
def enemy(x,y):
screen.blit(enemyImg, (x, y))
def fire_knife(x,y):
global knife_state
knife_state = "fire"
screen.blit(knifeImg,(x + 16, y + 10))
def isCollision(enemyX,enemyY,knifeX,knifeY):
distance = math.sqrt((math.pow(enemyX - knifeX,2)) + (math.pow(enemyY - knifeY,2)))
if distance < 27:
return True
else:
return False
#game loop
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
#if keystroke is pressed check whether its right or left
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -2
if event.key == pygame.K_RIGHT:
playerX_change = 2
if event.key == pygame.K_UP:
playerY_change = -2
if event.key == pygame.K_DOWN:
playerY_change = 2
if event.key == pygame.K_SPACE:
if knife_state is "ready":
# get the current x coordinate of yoshi
knifeX = playerX
fire_knife(playerX,knifeY)
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
playerY_change = 0
# RGB - Red, Green, Blue
screen.fill((0, 255, 0))
#add a wallpaper
bgimage=pygame.image.load("Background.png")
screen.blit(bgimage, (0, 0))
# 5 = 5 + -0.1 ->5 = 5 - 0.1
# 5 = 5 + 0.1
# checking for boundaries of yoshi/mushroom so it doesnt go out of bounds
playerX += playerX_change
if playerX < 0:
playerX = 0
elif playerX > 645:
playerX = 645
playerY += playerY_change
if playerY < 0:
playerY = 0
elif playerY > 500:
playerY = 500
# enemy movement
enemyX += enemyX_change
if enemyX <= 0:
enemyX_change = 2
enemyY += enemyY_change
elif enemyX > 645:
enemyX_change = -2
enemyY += enemyY_change
# knife movement
if knifeY <= 0:
knifeY = 480
knife_state = "ready"
if knife_state is "fire":
fire_knife(knifeX,knifeY)
knifeY -= knifeY_change
# collision
collision = isCollision(enemyX,enemyY,knifeX,knifeY)
if collision:
knifeY = 480
knife_state = "ready"
score += 1
print(score)
enemyX = random.randint(0,735)
enemyY = random.randint(50,150)
player(playerX,playerY)
enemy(enemyX,enemyY)
pygame.display.update()
I assume by "bullet" you are referring to "knife" in the code.
The code is not tracking the change in the knife's co-ordinates. Sure it's created at the player's X co-ordinate, but nothing remembers this change. So let's modify fire_knife() to simply remember the changes in the state of the knife, including the new X & Y.
def fire_knife( x, y ):
""" Start a knife flying upwards from the player """
global knife_state, knifeX, knifeY
knifeX = x + 16
knifeY = y + 10
knife_state = "fire"
And create a collision handler that automatically resets the knife back to "ready":
def knife_hits( enemyX, enemyY ):
""" Return True if the knife hits the enemy at the given (x,y).
If so, prepare the knife for firing again. """
global knife_state, knifeX, knifeY
collision_result = False
if ( knife_state == "fire" and isCollision( enemyX, enemyY, knifeX, knifeY ) ):
knife_state = "ready"
collision_result = True
return collision_result
Then create another function to separately draw the knife, if it's in the correct state.
def draw_knife( screen ):
""" If the knife is flying, draw it to the screen """
global knife_state, knifeImg, knifeX, knifeY
if ( knife_state == "fire" ):
screen.blit( knifeImg, ( knifeX, knifeY ) )
And, for the sake of completeness, a function to update the knife's position, and reset the knife_state when it goes off-screen.
def update_knife():
""" Make any knife fly up the screen, resetting at the top """
global knife_state, knifeX, knifeY, knifeY_change
# if the knife is already flying, move it
if ( knife_state == "fire" ):
knifeY -= knifeY_change
if ( knifeY <= 0 ):
knife_state = "ready" # went off-screen
So that gives a new main loop calling these functions:
#game loop
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
#if keystroke is pressed check whether its right or left
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -2
if event.key == pygame.K_RIGHT:
playerX_change = 2
if event.key == pygame.K_UP:
playerY_change = -2
if event.key == pygame.K_DOWN:
playerY_change = 2
if event.key == pygame.K_SPACE:
if knife_state is "ready":
# Fire the knife at the coordinates of yoshi
fire_knife( playerX, playerY ) # create a new flying knife
# ...
# enemy movement
enemyX += enemyX_change
if enemyX <= 0:
enemyX_change = 2
enemyY += enemyY_change
elif enemyX > 645:
enemyX_change = -2
enemyY += enemyY_change
update_knife() # move the flying knife (if any)
if ( knife_hits( enemyX, enemyY ) ): # is there a knife-enemy-collision?
score += 1
print(score)
enemyX = random.randint(0,735)
enemyY = random.randint(50,150)
else:
draw_knife( screen ) # paint the flying knife (if any)
player(playerX,playerY)
enemy(enemyX,enemyY)
pygame.display.update()
Putting all the modifications to the knife position into functions makes your main loop simpler, and keeps most knife-code contained into a single group of functions. It would probably be better again to make a Knife class with these functions, but this is a simple start.

How to make your character move without tapping repeatedly on buttons?

I'm working on a racing game. I have been using this code but my player keeps moving once only. How do I solve this problem?
change = 7
dist = 7
change_r = 0
change_l = 0
dist_u = 0
dist_d = 0
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
change_r = True
elif event.key == pygame.K_LEFT:
change_l = True
elif event.key == pygame.K_UP:
dist_u = True
elif event.key == pygame.K_DOWN:
dist_d = True
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or event.key == pygame.K_LEFT or event.key == pygame.K_UP or event.key == pygame.K_DOWN:
change_r = False
change_l = False
dist_u = False
dist_d = False
clock.tick(60)
if change_r == True:
x += change
if change_l == True:
x -= change
if dist_u == True:
y -= dist
if dist_d == True:
y += dist
There are different ways you could go about making move-able shapes/sprites using Pygame. The code you posted in your question seems overly complex. I'll give you two different ways that are simpler, and easier to use. Using a sprite class, and using a function.
It may not seem like I'm answering your question, but if I just told you what to fix in your code you posted, I'd just be knowingly steering you down a road that will lead to many problems, and much complexity in the future.
Method 1: Using a sprite class
To make a your race car sprite, you could use a sprite class like the one below.
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((50, 50))
self.image.fill((255, 0, 0))
self.rect = self.image.get_rect()
self.rect.x = WIDTH / 2
self.rect.y = HEIGHT / 2
self.vx = 0
self.vy = 0
def update(self):
self.vx = 0
self.vy = 0
key = pygame.key.get_pressed()
if key[pygame.K_LEFT]:
self.vx = -5
elif key[pygame.K_RIGHT]:
self.vx = 5
if key[pygame.K_UP]:
self.vy = -5
elif key[pygame.K_DOWN]:
self.vy = 5
self.rect.x += self.vx
self.rect.y += self.vy
Since your class is inheriting from Pygame's sprite class, You must name your image self.image and you must name your rectangle for the image self.rect. As you can also see, the class has two main methods. One for creating the sprite(__init__) and one for updating the sprite(update)
To use your class, make a Pygame sprite group to hold all your sprites, and then add your player object to the group:
sprites = pygame.sprite.Group()
player = Player()
sprtites.add(player)
And to actual render your sprites to the screen call sprites.update() and sprites.draw() in your game loop, where you update the screen:
sprites.update()
window_name.fill((200, 200, 200))
sprites.draw(window_name)
pygame.display.flip()
The reason i highly recommended using sprite classes, is that it will make your code look much cleaner, and be much easier to maintain. You could even move each sprite class to their own separate file.
Before diving fully into the method above however, you should read up on pygame.Rect objects and pygame.sprite objects, as you'll be using them.
Method 2: Using A function
If you prefer not to get into sprite classes, you can create your game entities using a function similar to the one below.
def create_car(surface, x, y, w, h, color):
rect = pygame.Rect(x, y, w, h)
pygame.draw.rect(surface, color, rect)
return rect
If you would still like to use a sprites, but don't want to make a class just modify the function above slightly:
def create_car(surface, x, y, color, path_to_img):
img = pygame.image.load(path_to_img)
rect = img.get_rect()
surface.blit(img, (x, y))
Here is an example of how i would use the functions above to make a movable rectangle/sprite:
import pygame
WIDTH = 640
HEIGHT = 480
display = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Moving Player Test")
clock = pygame.time.Clock()
FPS = 60
def create_car(surface, x, y, w, h, color):
rect = pygame.Rect(x, y, w, h)
pygame.draw.rect(surface, color, rect)
return rect
running = True
vx = 0
vy = 0
player_x = WIDTH / 2 # middle of screen width
player_y = HEIGHT / 2 # middle of screen height
player_speed = 5
while running:
clock.tick(FPS)
for e in pygame.event.get():
if e.type == pygame.QUIT:
running = False
pygame.quit()
quit()
if e.type == pygame.KEYDOWN:
if e.key == pygame.K_LEFT:
vx = -player_speed
elif e.key == pygame.K_RIGHT:
vx = player_speed
if e.key == pygame.K_UP:
vy = -player_speed
elif e.key == pygame.K_DOWN:
vy = player_speed
if e.type == pygame.KEYUP:
if e.key == pygame.K_LEFT or e.key == pygame.K_RIGHT or\
e.key == pygame.K_UP or e.key == pygame.K_DOWN:
vx = 0
vy = 0
player_x += vx
player_y += vy
display.fill((200, 200, 200))
####make the player#####
player = create_car(display, player_x, player_y, 10, 10, (255, 0, 0))
pygame.display.flip()
As you may see above, your code for moving your race car can be simplified.
I should note, I'm assuming a few things with each method outlined above.
That your either using a circle, square, or some type of pygame shape object.
Or that your using a sprite.
If your not currently using any of the methods outlined above, I suggest that you do. Doing so will make your code much eaiser to maintain once you begin to build larger and more complex games.
You should have a global loop irrespective of your event handling. You should place your clock.tick() and your movement there. Namely:
#some constants here
while True:
pygame.display.update()
clock.tick(60)
#update you game state
if change_r == True:
x += change
if change_l == True:
x -= change
if dist_u == True:
y -= dist
if dist_d == True:
y += dist
for event in pygame.event.get():
# react to player input by changing the game state

unable to effectively spawn sprites in a controlled manor in python 2.7 with pygame

My goal for this question is to be able to achieve an answer which explains how to make it so that when my character moves around to pick up the 'baddie(s)', the baddies will then automatically re-spawn onto the screen. Keeping total amount of sprites on the screen at any one time for the player to pick up at 40.
I am having problems being able to control the way the 'pikachu.jpg' sprites spawn. I am either able to spawn the sprites solely in a group fashion by entering an integer into my program manually or i write my attempt to test it wrong and the program upholds an infinite loop of drawing baddie sprites. I had set up a system which i believed should have coped with keeping the baddies at 40 sprites solid, though it did not work. I am not very good with python yet and i would really appreciate help with this issue.
import necessary pygame modules
import sys
import random
import time
import pygame
from pygame.locals import *
# initialise pygame
pygame.init()
# define window width and height variables for ease of access
WindowWidth = 600
WindowHeight = 500
global PLAY
PLAY = False
x = 600 / 3
y = 460 / 2 - 25
# load and define image sizes
enemyImage = pygame.image.load('pikachu.jpg')
enemyStretchedImage = pygame.transform.scale(enemyImage, (40,40))
screen = pygame.display.set_mode((WindowWidth, WindowHeight))
def play(PLAY):
playerImage = pygame.image.load('player.jpg')
playerStretchedImage = pygame.transform.scale(playerImage, (40, 40))
movex,movey = 0,0
charx, chary=300, 200
enemyy, enemyx = 10, 10
moveright = False
moveleft = False
spawn = True
direction = 'down'
baddie = []
for i in range(20):
baddie.append(pygame.Rect(random.randint(0, WindowWidth - 40), random.randint(0, 0), 40, 40))
while True:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == ord('m'):
pygame.mixer.music.stop()
music = False
if event.key == ord('n'):
pygame.mixer.music.play()
music = True
if event.key == ord('a'):
moveleft = True
if event.key == ord('d'):
moveright = True
if event.key == ord('w'):
movey = -0.5
if event.key == ord('s'):
movey = 0.5
if event.key == ord('p'):
time.sleep(5)
if event.type ==KEYUP:
if event.key == ord('a'):
moveleft = False
if moveleft == False:
movex = 0
if event.key == ord('d'):
moveright = False
if moveright == False:
movex = 0
if event.key == ord('w'):
movey = 0
if event.key == ord('s'):
movey = 0
elif event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == MOUSEBUTTONDOWN:
pygame.quit()
sys.exit()
screen.fill(pygame.Color("red"))
player = pygame.Rect(charx, chary, 40, 40)
if direction == 'down':
enemyy += 0.1
if moveright ==True:
movex = 0.5
if moveleft ==True:
movex = -0.5
if player.bottom > WindowHeight:
chary = WindowHeight - 40
movey = 0
if player.top < 0:
chary = 1
movey = 0
if player.left < 0:
charx = 1
movex = 0
if player.right > WindowWidth:
charx = WindowWidth - 40
movex = 0
for bad in baddie[:]: #Here is where my attempt of testing was.
if bad < 40:
spawn = True
if bad >= 40:
spawn = False
if spawn == True:
baddie.append(pygame.Rect(random.randint(0, WindowWidth - 40), random.randint(0,0), 40, 40))
screen.blit(playerStretchedImage, player)
charx+=movex
chary+=movey
for bad in baddie[:]:
if player.colliderect(bad):
baddie.remove(bad)
for bad in baddie:
screen.blit(enemyStretchedImage, bad)
pygame.display.update()
def presskey():
myfont = pygame.font.SysFont("monospace", 30)
label = myfont.render("press space to play!", 1, (255,125,60))
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_SPACE:
PLAY = True
if PLAY == True:
play(PLAY)
return
screen.fill(pygame.Color("cyan"))
screen.blit(label, (x,y))
pygame.display.update()
presskey()
Here you're trying to fill up count of baddies up to 40, but the bad is a rectangle and you're using it as a number of buddies:
for bad in baddie[:]: #Here is where my attempt of testing was.
if bad < 40:
spawn = True
if bad >= 40:
spawn = False
if spawn == True:
baddie.append(pygame.Rect(random.randint(0, WindowWidth - 40), random.randint(0,0), 40, 40))
I suggest you to replace those lines with:
if len(baddie)<40:
baddie.append(pygame.Rect(random.randint(0, WindowWidth - 40),
You can get the number of items in your [] list using len(baddie). You should get a new baddie each game loop cycle.

Categories

Resources