Libtcod python 3 crashing when trying to move character? - python

I'm trying to make a basic roguelike and following this tutorial: http://www.roguebasin.com/index.php?title=Complete_Roguelike_Tutorial,_using_python3%2Blibtcod,_part_1
I tried to make a character respond to mouse movements using libtcod. I followed the tutorial and all was going well, my character appeared on the screen, but for some reason the program crashes when I try to execute a movement command. For reference, my code is here:
import libtcodpy as tcod
SCREEN_WIDTH = 80
SCREEN_HEIGHT = 50
LIMIT_FPS = 20
font_path = 'arial10x10.png' # this will look in the same folder as this script
font_flags = tcod.FONT_TYPE_GREYSCALE | tcod.FONT_LAYOUT_TCOD # the layout may need to change with a different font file
tcod.console_set_custom_font(font_path, font_flags)
window_title = 'Python 3 libtcod tutorial'
fullscreen = False
tcod.console_init_root(SCREEN_WIDTH, SCREEN_HEIGHT, window_title, fullscreen)
playerx = SCREEN_WIDTH // 2
playery = SCREEN_HEIGHT // 2
def handle_keys():
# movement keys
key = tcod.console_check_for_keypress()
if tcod.console_is_key_pressed(tcod.KEY_UP):
playery = playery - 1
elif tcod.console_is_key_pressed(tcod.KEY_DOWN):
playery = playery + 1
elif tcod.console_is_key_pressed(tcod.KEY_LEFT):
playerx = playerx - 1
elif tcod.console_is_key_pressed(tcod.KEY_RIGHT):
playerx = playerx + 1
while not tcod.console_is_window_closed():
tcod.console_set_default_foreground(0, tcod.white)
tcod.console_put_char(0, playerx, playery, '#', tcod.BKGND_NONE)
tcod.console_flush()
exit = handle_keys()
if exit:
break
I posted the question to another forum and they said I should define playerx and playery as global, so I added that to the handle_keys() function but then it just crashes on startup.

Here is the fix, in the handle_keys function:
You were missing a global assignment as well, and using an incorrect check for key values
def handle_keys():
global playerx, playery
# movement keys
key = tcod.console_check_for_keypress()
if key.vk == tcod.KEY_UP:
playery = playery - 1
elif key.vk == tcod.KEY_DOWN:
playery = playery + 1
elif key.vk == tcod.KEY_LEFT:
playerx = playerx - 1
elif key.vk == tcod.KEY_RIGHT:
playerx = playerx + 1
By the way, there is now an updated python3 tutorial here: http://rogueliketutorials.com

Related

space invader pygame make enemy disappear when shot

I have a list with all my enemies and when the distance between the players bullet and the enemy is close enough, I can make a enemy disappear but its never the right one that was hit with the bullet, its always the enemy with the greatest x value(in my case the one at the end of the list) so my questions is how do I make the specific enemy disappear. here is my code for reference.
import pygame
import random
import math
# initalize pygame
pygame.init()
# creates game screen to display game
game_window = pygame.display.set_mode((800, 570))
# Title and icon for window
pygame.display.set_caption("Power of the Doctor")
icon = pygame.image.load('tardisShooter.png')
pygame.display.set_icon(icon)
# backgroun picture
background = pygame.image.load('SpaceTardissmall.png')
# player info
Playerimg = pygame.image.load('tardisShooter.png')
playerx = 370 # players x axis
playery = 470 # players y axis
playerx_change = 0 # adds constant change while added in loop
def player(x, y):
# blit draws image on screen: x axis y axis
game_window.blit(Playerimg, (x, y))
# enemy info
Enemyimg = []
enemyx = []
enemyy = []
enemyx_change = 1
enemyy_change = 0
num_enemies = 2
enemyspawnx = 50
enemyspawny = 200
for i in range(num_enemies):
Enemyimg.append(pygame.image.load('CybermanShooter.png'))
enemyx.append(enemyspawnx) # random x axis for enemy
enemyy.append(enemyspawny) # random y axis for enemy
enemyspawnx += 70
def enemy(x, y, i):
game_window.blit(Enemyimg[i], (x, y))
# bullet info
bulletimg = pygame.image.load('torpedo32.png')
bullety = playery
bulletx = playerx
bulletstate = "idle"
bullety_change = 5
def bullet(x, y):
global bulletstate
bulletstate = "FIRE"
game_window.blit(bulletimg, (x + 15.5, y - 25))
def collision(enemyx, enemyy, bulletx, bullety):
distance = math.sqrt((math.pow(bulletx - enemyx, 2)) + (math.pow(bullety - enemyy, 2)))
if distance < 27:
return True
else:
return False
rand = random.randint(0, num_enemies)
# timer info
bulletevent = pygame.USEREVENT
pygame.time.set_timer(bulletevent, 2000)
# get a rabdom number
# when the timer hits 2 secodsn spawsn bomb at the index of the random number that corresponds witht the enemy
# enemy bomb
bombimg = []
bombx = []
bomby = []
bomby_change = 1
bombstate = "idle"
num_bombs = 2
for i in range(num_bombs):
bombimg.append(pygame.image.load('bomb.png'))
bombx.append(enemyx[i])
bomby.append(enemyy[i])
def bomb(x, y, i):
global bombstate
bombstate = "fire"
game_window.blit(bombimg[i], (x + 15, y + 65))
# player hit detection
def enemyhit(bombx, bomby, x, y):
distance2 = math.sqrt((math.pow(bombx - x, 2)) + (math.pow(bomby - (y - 50), 2)))
if distance2 < 20:
return True
else:
return False
# loop to keep screen running
Running = True
while Running:
# background color
game_window.fill((0, 0, 0))
# background image in loop
game_window.blit(background, (0, 0))
# checks anything typed while game is running
for event in pygame.event.get():
# if they click x to quit close window
if event.type == pygame.QUIT:
Running = False
if event.type == bulletevent:
if bombstate == 'idle':
bomb(bombx[rand], bomby[rand], i)
bombx[rand] = enemyx[rand]
bomby[rand] = enemyy[rand]
# means key has been pressed(not released)
if event.type == pygame.KEYDOWN:
# escape key closes game
if event.key == pygame.K_ESCAPE:
Running = False
# right key moves player 5 spaces
if event.key == pygame.K_RIGHT:
playerx_change = 5
# left key moves players back 5 spaces
if event.key == pygame.K_LEFT:
playerx_change = -5
if event.key == pygame.K_SPACE:
bulletx = playerx
if bulletstate == "idle":
bullet(bulletx, bullety)
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or event.key == pygame.K_LEFT:
playerx_change = 0
playerx += playerx_change # constantly adds user input to player model
# player bounds
if playerx >= 740:
playerx = 740
if playerx <= 0:
playerx = 0
# player fucntion draws image
player(playerx, playery)
# loops through all the items in the lists named
for i in range(num_enemies):
# draws all enemies
enemy(enemyx[i], enemyy[i], i)
enemyx[i] += enemyx_change
if enemyx[i] >= 735:
enemyx_change = -.8
enemyy[i] += 10
if enemyx[i] <= 0:
enemyx_change = .8
enemyy[i] += 10
# is state is fire
if bulletstate == "FIRE":
# draws torpepd at coordinates
bullet(bulletx, bullety)
bullety -= bullety_change # decreases y axis moving bullet
if bullety <= 0: # if goes past border
bulletstate = "idle" # ittl switch back to idle
bullety = playery # moves bullet y back to player y
for i in range(num_enemies):
collided = collision(enemyx[i], enemyy[i], bulletx, bullety)
if collided == True:
bulletstate = 'idle'
bullety = playery
Enemyimg.remove(Enemyimg[i])
num_enemies -= 1
# when enemy fires
if bombstate == 'fire':
bomb(bombx[rand], bomby[rand], i)
bomby[rand] += bomby_change
if bomby[rand] > 570:
bombstate = 'idle'
bomby[rand] = enemyy[rand]
rand = random.randint(0, 1)
# enemy bullets hit player
enemyhits = enemyhit(bombx[rand], bomby[rand], playerx, playery)
if enemyhits == True:
playerx = 370
bombstate = 'idle'
bomby[rand] = enemyy[rand]
# updates the screen in loop
pygame.display.update()
A big problem with your code is having different lists for each attribute of your enemies.
You wrote this :
Enemyimg = []
enemyx = []
enemyy = []
Meaning that you always need to sync those three lists at all time to get coherent results. Which you are not doing, when you "remove" an enemy, you just remove the img from Enemyimg and not removing its coords in enemyy and enemyx.
While you could manage to make it work with three lists, you are just overcomplicating things. Let me show you what you may want to do to make your life way easier :)
I'm going to assume, you don't know about OOP (Object Oriented Programming) yet ? I Would be a great time to use it but it can be a little complexe if you are just starting out with programming.
So let's introduce python's dict !
What you really want to do is have one single list :
enemies = []
But how to store everything in one list you might wonder ?
Well, it will be a list of dict. A dict looks something like that :
example = {'image': pygame.image.load('CybermanShooter.png'), 'x': enemyspawnx, 'y': enemyspawny}
(Note that if you always use the same image, you don't need to put it here, you can just draw your image at the position)
Now if you do something like :
print(example['x'])
It will print your enemy's x value.
So, to sum up :
You want to have one single list : enemies = []
To add an enemy you will do :
enemies.append({'image': pygame.image.load('CybermanShooter.png'), 'x': enemyspawnx, 'y': enemyspawny})
To detect your collisions :
# Your collision function
def collision(enemy, bulletx, bullety):
distance = math.sqrt((math.pow(bulletx - enemy['x'], 2)) + (math.pow(bullety - enemy['y'], 2)))
if distance < 27:
return True
return False
# Your loop (in 2 steps: 1 - find enemies to remove, 2 - actually remove them)
enemies_to_remove = []
for enemy in enemies :
if collision(enemy, bulletx, bullety):
bulletstate = 'idle'
bullety = playery
enemies_to_remove.append(enemy)
num_enemies -= 1
for enemy in enemies_to_remove:
enemies.remove(enemy)
To draw your enemies:
# Your draw_enemy function (which you called `enemy(...)` for some reason)
def draw_enemy(enemy):
game_window.blit(enemy['image'], (enemy['x'], enemy['y']))
# Inside the main loop
for enemy in enemies:
draw_enemy(enemy)
To update the position of enemies:
# Make a move_enemy function
def move_enemy(enemy):
# put your moving logic here
# Inside the main loop:
for enemy in enemies:
move_enemy(enemy)
Do you get the principle ?
I've tried to stay as close as your original code as possible so it's not too many information to take in at once.
But technically you should apply the same principle for your bullets and to some extend to your player.

what is Not BytesIO?

I'm kind of new to this site and pygame and I was hoping for a bit of help. So I made this space invader clone which is about 180 lines right, when I run it on Pycharm, it works fine. So I decided to try testing it out further and tried converting it into an .exe file which is where my troubles began. Every time I try running the .exe, this message appears
Traceback (most recent call last):
File "main.py", line 62, in <module>
font = pygame.font.Font('freesansbold.ttf',32)
TypeError: expected str, bytes or os.PathLike object, not BytesIO
I used freeCodeCamp.org's template and applied my own customs, here's a video incase you're interested: https://www.youtube.com/watch?v=FfWpgLFMI7w&t=7041s
Here's the code as well:
import math
import random
import pygame
from pygame import mixer
# Initialize the pygame
pygame.init()
# Create the screen
screen = pygame.display.set_mode((600, 400))
# Background Sound
mixer.music.load('Here he comes.mp3')
mixer.music.play(-1)
# Title and icon
pygame.display.set_caption("Defender of The Blue")
icon = pygame.image.load("Submarine of Vengeance.png")
pygame.display.set_icon(icon)
# Player
playerImg = pygame.image.load('Protagonist.png')
playerX = 250
playerY = 300
playerX_change = 0
# Enemy
enemyImg = []
enemyX = []
enemyY = []
enemyX_change = []
enemyY_change = []
num_of_enemies = 6
for i in range(num_of_enemies):
enemyImg.append(pygame.image.load('Antagonist.png'))
enemyX.append(random.randint(0, 500))
enemyY.append(random.randint(10, 100))
enemyX_change.append(0.1)
enemyY_change.append(20)
# Energy Blast
# Ready - You can't see the bullet state on the screen
# Fire - The blast is currently moving
energyblastImg = pygame.image.load('energy-blasts.png')
energyblastX = 0
energyblastY = 300
energyblastX_change = 0
energyblastY_change = 1
energyblast_state = "ready"
# score
score_value = 0
font = pygame.font.Font('freesansbold.ttf',32)
textX = 10
textY = 10
game_over_font = pygame.font.Font('freesansbold.ttf',50)
# Game Over Text
def show_score(x,y):
score = font.render("Score :" + str(score_value),True, (250,100,0))
screen.blit(score, (x, y))
def game_over_text():
game_over_text = game_over_font.render("GAME OVER",True, (250,0,0))
screen.blit(game_over_text, (150, 100))
def player(x, y):
screen.blit(playerImg, (x, y))
def enemy(x, y, i):
screen.blit(enemyImg[i], (x, y))
def fire_energyblast(x, y):
global energyblast_state
energyblast_state = "fire"
screen.blit(energyblastImg, (x + -1, y + 10))
def isCollison(enemyX, enemyY, energyblastX, energyblastY):
distance = math.sqrt((math.pow(enemyX - energyblastX, 2)) + (math.pow(enemyY - energyblastY, 2)))
if distance < 27:
return True
else:
return False
# Game Loop
running = True
while running:
# RGB = Red, Green, Blue
screen.fill((0, 0, 128))
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 = -1
if event.key == pygame.K_RIGHT:
playerX_change = 1
if event.key == pygame.K_SPACE:
if energyblast_state is "ready":
energyblast_sound = mixer.Sound('Energy Blast.mp3')
energyblast_sound.play()
# Get the current x coordinate of the submarine
energyblastX = playerX
fire_energyblast(energyblastX, energyblastY)
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change = 0
# 5 = 5 + -0.1 -> 5 = 5 - 0.1
# 5 = 5 + 0.1
# Checking for boundaries of submarine so it doesn't go out of bounds
playerX += playerX_change
if playerX <= 0:
playerX = 0
elif playerX >= 500:
playerX = 500
# enemy movement
for i in range(num_of_enemies):
# Game Over
if enemyY[i] > 272:
for j in range(num_of_enemies):
enemyY[j] = 2000
game_over_text()
break
enemyX[i] += enemyX_change[i]
if enemyX[i] <= 0:
enemyX_change[i] = 1
enemyY[i] += enemyY_change[i]
elif enemyX[i] >= 500:
enemyX_change[i] = -1
enemyY[i] += enemyY_change[i]
# Collision
collison = isCollison(enemyX[i], enemyY[i], energyblastX, energyblastY)
if collison:
explosion_Sound = mixer.Sound('Explode.mp3')
explosion_Sound.play()
energyblastY = 300
energyblast_state = "ready"
score_value += 50
enemyX[i] = random.randint(0, 500)
enemyY[i] = random.randint(10, 100)
enemy(enemyX[i],enemyY[i], i)
# energy blast movement
if energyblastY <= 0:
energyblastY = 300
energyblast_state = "ready"
if energyblast_state is "fire":
fire_energyblast(energyblastX, energyblastY)
energyblastY -= energyblastY_change
player(playerX, playerY)
show_score(textX,textY)
pygame.display.update()
I'm not quite sure what BytesIO is. Is it like having something used twice and cancels out? How can I change this?
Are you certain that "freesansbold.ttf" is downloaded and in the same directory as the code youre trying to run, if this isnt possible for whatever reason you should be able to replace the
font = pygame.font.Font('freesansbold.ttf',32)
with
font = pygame.font.Font('(file path)freesansbold.ttf',32)

player gets stuck after hitting boundary in pygame [duplicate]

This question already has answers here:
Not letting the character move out of the window
(2 answers)
Closed 1 year ago.
When my player hits one of the boundaries with the value 0 it is perfectly fine and can move freely throughout the world. But when my player hits a boundary with the value 485, it fine until you try and move up. Then depending on the boundary you hit it will get stuck at playerX = 249 or playerY = 249
import pygame
import time
pygame.init()
playerX = 250 # Player X locale
playerY = 250 # Players Y locale
playerSpeed = 2
backgroundX = 0 # Background X locale
backgroundY = 0 # Background Y locale
### LOADS PLAYER IMAGES ###
playerFrontImg = pygame.image.load("Images/Player Images/playerBackOne.png")
playerBackImg = pygame.image.load("Images/Player Images/playerFrontOne.png")
playerLeftImg = pygame.image.load("Images/Player Images/playerLeftOne.png")
playerRightImg = pygame.image.load("Images/Player Images/playerRightOne.png")
playerCurrentImg = playerFrontImg
### LOADS PLAYER IMAGES ###
### LOADS MAP IMAGES ###
testMap = pygame.image.load("Images/Map Images/TEST_MAP.png")
### LOADS MAP IMAGES ###
screen = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()
running = True
while running:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
### KEYBOARD INPUTS AND MOVEMENTS ###
keys = pygame.key.get_pressed() # gets pressed keys and assigns it TRUE or FALSE
if keys[pygame.K_w]: # Checks if "w" is pressed
playerCurrentImg = playerFrontImg # Changes current image to correct image
if playerY == 250:
if backgroundY < 0:
backgroundY += playerSpeed
if backgroundY >= 0 or playerY > 250:
playerY -= playerSpeed
if playerY <= 0:
playerY = 0
if keys[pygame.K_s]: # Checks if "s" is pressed
playerCurrentImg = playerBackImg # Changes current image to correct image
if playerY == 250:
if backgroundY > -500:
backgroundY -= playerSpeed
if backgroundY <= -500 or playerY < 250:
playerY += playerSpeed
if playerY >= 485:
playerY = 485 # THIS SEEMS TO BE WHERE THE ISSUE IS
if keys[pygame.K_a]:
playerCurrentImg = playerLeftImg # Changes current image to correct image
if playerX == 250:
if backgroundX < 0:
backgroundX += playerSpeed
if backgroundX >= 0 or playerX > 250:
playerX -= playerSpeed
if playerX <= 0:
playerX = 0
if keys[pygame.K_d]:
playerCurrentImg = playerRightImg # Changes current image to correct image
if playerX == 250:
if backgroundX > -500:
backgroundX -= playerSpeed
if backgroundX <= -500 or playerX < 250:
playerX += playerSpeed
if playerX >= 485:
playerX = 485
if keys[pygame.K_f]: # TROUBLE SHOOTING KEY
print(playerX, playerY, "\n", backgroundX, backgroundY)
time.sleep(1)
### KEYBOARD INPUTS AND MOVEMENTS ###
screen.blit(testMap, (backgroundX, backgroundY))
screen.blit(playerCurrentImg, (playerX, playerY))
pygame.display.update()
pygame.quit()
quit()
A case of a single symbol.
The critical code is this:
if keys[pygame.K_w]: # Checks if "w" is pressed
playerCurrentImg = playerFrontImg # Changes current image to correct image
if playerY == 250:
if backgroundY < 0:
backgroundY += playerSpeed
if backgroundY >= 0 or playerY > 250:
playerY -= playerSpeed
if playerY <= 0:
playerY = 0
It is meant to be playerY <= 250 and it is also best pratices to use and instead of nested ifs. Your code should look like this.
if keys[pygame.K_w]: # Checks if "w" is pressed
playerCurrentImg = playerFrontImg # Changes current image to correct image
if playerY <= 250 and backgroundY < 0:
backgroundY += playerSpeed
if backgroundY >= 0 or playerY > 250:
playerY -= playerSpeed
if playerY <= 0:
playerY = 0

The pygame code and the error is mentioned below: [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
Here is a source code of my space-arcade pygame. It's a quite simple one and doesn't shoots bullets. Only that we can move the player with the obstacles being moved as well. However, the limit for the spaceship (player) to move in the screen has been set from x = 0 to x = 765 and from y = 200 to y = 480. But the spaceship somehow cross the limit for y-axis i.e it can move beyond y = 0 and y = 600, but only at some specific x-axis like when x is 10 and 590 something. How can i fix this gap in the following python code:
import random
pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Space Invader")
icon = pygame.image.load("space-invaders.png")
pygame.display.set_icon(icon)
background = pygame.image.load("background.png")
player_image = pygame.image.load("space-invaders.png")
playerX = 370
playerY = 480
playerX_change = 0
playerY_change = 0
def player(x, y):
screen.blit(player_image, (x, y))
obs_image = pygame.image.load("cave-painting (1).png")
obsX = random.randint(0, 800)
obsY = random.randint(0, 100)
obsX_change = 2
obsY_change = 0.3
def obstacle(x, y):
screen.blit(obs_image, (x, y))
running = True
while running:
screen.fill( (0, 0,0) )
screen.blit(background, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -4
if event.key == pygame.K_RIGHT:
playerX_change = 4
if event.key == pygame.K_UP:
playerY_change = -4
if event.key == pygame.K_DOWN:
playerY_change = 4
if event.type == pygame.KEYUP:
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
playerX += playerX_change
playerY += playerY_change
# Stopping our player beyond screen:
if playerX <= 0:
playerX = 0
elif playerX >= 765:
playerX = 765
elif playerY <= 200:
playerY = 200
elif playerY >= 480:
playerY = 480
obsX += obsX_change
obsY += obsY_change
# Movement mechanics for obstacles:
if obsX <= 0:
obsX_change = 3
obsY += obsY_change
elif obsX >= 736:
obsX_change = -3
obsY += obsY_change
player(playerX, playerY)
obstacle(obsX, obsY)
pygame.display.update()```
Here are the source pictures used in the aforementioned code:
[background][1]
[cave-painting (1)][2]
[space-invaders][3]
[1]: https://i.stack.imgur.com/EZFLs.png
[2]: https://i.stack.imgur.com/CxNs4.png
[3]: https://i.stack.imgur.com/Z97n7.png
Don't use elif. You're code says (pseudocode):
If x is beyond or equal to 0 then go back to zero
If x is not beyond or equal to 0 but x is beyond or equal to 765 then go back to 765
If none of the above are true but y is beyond or equal to 200 then go back to 200
Do you see the problem? If x is equal to 0, then the y-checks never occur. Change the third elif to if to fix this issue. Here's the fixed code:
if playerX <= 0:
playerX = 0
elif playerX >= 765:
playerX = 765
if playerY <= 200:
playerY = 200
elif playerY >= 480:
playerY = 480
These comparisons should be independent from each other.
By chaining then in a single if/elif/elif/... block, the checks
beyond the first only take place if the first check fails, and so on.
Given the nature of your problem, this is likely the cause.
Just replace the elif statements by plain ifs: each check will
run independently and fix the limits it should guard:
# Stopping our player beyond screen:
if playerX <= 0:
playerX = 0
elif playerX >= 765:
playerX = 765
elif playerY <= 200:
playerY = 200
elif playerY >= 480:
playerY = 480
You can simplify you code. Use pygame.key.get_pressed() to move the player smoothly, rather than the keyboard events KEYDOWN and KEYDUP. pygame.key.get_pressed() returns a list with the state of each key. If a key is held down, the state for the key is True, otherwise False:
keys = pygame.key.get_pressed()
playerX += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * 4
playerY += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * 4
Use pygame.Rect objects and pygame.Rect.clamp() respectively pygame.Rect.clamp_ip() to limit the position of the player to a rectangular area.
border_rect = pygame.Rect(0, 200, 800, 312)
player_rect = player_image.get_rect(topleft = (playerX, playerY))
player_rect.clamp_ip(border_rect)
playerX, playerY = player_rect.topleft
Or even shorter:
keys = pygame.key.get_pressed()
playerX, playerY = player_image.get_rect(topleft = (playerX, playerY)) \
.move((keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * 4, \
(keys[pygame.K_DOWN] - keys[pygame.K_UP]) * 4) \
.clamp((0, 200, 800, 312)).topleft
Example code:
running = True
while running:
screen.blit(background, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
keys = pygame.key.get_pressed()
playerX += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * 4
playerY += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * 4
border_rect = pygame.Rect(0, 200, 800, 312)
player_rect = player_image.get_rect(topleft = (playerX, playerY))
player_rect.clamp_ip(border_rect)
playerX, playerY = player_rect.topleft
obsX += obsX_change
obsY += obsY_change
# Movement mechanics for obstacles:
if obsX <= 0:
obsX_change = 3
obsY += obsY_change
elif obsX >= 736:
obsX_change = -3
obsY += obsY_change
player(playerX, playerY)
obstacle(obsX, obsY)
pygame.display.update()

How to create a variable with code (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)

Categories

Resources