I'm trying to make a little game, and I came across a problem which I can't seem to figure out. The problem is that my sprite isn't moving after creating the game loop and the if statements with the keyup's and what not. Can you guys figure it out and tell me why it's not working?
Here's my code so far:
import pygame, sys, random
from pygame.locals import *
pygame.init()
mainClock = pygame.time.Clock()
windowWidth = 600
windowHeight = 400
windowSize = (600, 400)
windowSurface = pygame.display.set_mode((windowWidth, windowHeight), 0, 32)
display = pygame.Surface((300, 200))
black = (0, 0, 0)
white = (225, 225, 255)
green = (0, 255, 0)
moveRight = False
moveLeft = False
moveSpeed = 6
level= [['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'],
['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'],
['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'],
['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'],
['0','0','0','0','0','0','0','2','2','2','2','2','0','0','0','0','0','0','0'],
['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'],
['2','2','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','2','2'],
['1','1','2','2','2','2','2','2','2','2','2','2','0','0','2','2','2','1','1'],
['1','1','1','1','1','1','1','1','1','1','1','1','0','0','1','1','1','1','1'],
['1','1','1','1','1','1','1','1','1','1','1','1','0','0','1','1','1','1','1'],
['1','1','1','1','1','1','1','1','1','1','1','1','0','0','1','1','1','1','1'],
['1','1','1','1','1','1','1','1','1','1','1','1','0','0','1','1','1','1','1'],
['1','1','1','1','1','1','1','1','1','1','1','1','0','0','1','1','1','1','1']]
grass = pygame.image.load('grass.png')
dirt = pygame.image.load('dirt.png')
player = pygame.image.load('player.png').convert()
playerRect = pygame.Rect(100, 100, 5, 13)
player.set_colorkey((255,255,255))
while True:
display.fill((214, 42, 78))
#display.blit(player,(playerRect.x,playerRect.y))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.type == pygame.K_RIGHT or event.key == pygame.K_d:
moveRight = True
if event.type == pygame.K_LEFT or event.key == pygame.K_a:
moveLeft = False
if event.type == pygame.KEYUP:
if event.type == pygame.K_RIGHT or event.key == pygame.K_d:
moveRight = False
if event.type == pygame.K_LEFT or event.key == pygame.K_a:
moveLeft = False
display.blit(player,(playerRect.x,playerRect.y))
playerMovement = [0, 0]
if moveRight == True:
playerMovement[0] += 2
if moveLeft == True:
playerMovement[0] -= 2
tileRect = []
y = 0
for row in level:
x = 0
for col in row:
if col == '2':
display.blit(grass, (x*16, y*16))
if col == '1':
display.blit(dirt, (x*16, y*16))
if col != '0':
tileRect.append(pygame.Rect(x*16,y*16,16,16))
x += 1
y += 1
#pygame.draw.rect(windowSurface, black, player)
windowSurface.blit(pygame.transform.scale(display, windowSize),(0,0))
pygame.display.update()
mainClock.tick(60)
I've restructured your main loop to fix the problems. I change the playerMovement (velocity) in the event loop now and use it to update the playerRect in the main loop with the pygame.Rect.move_ip method.
By the way, you can pass the playerRect to blit to blit the image at the topleft (x, y) coords.
# The player's velocity. Define it outside of the main loop.
playerMovement = [0, 0]
while True:
# Handle events.
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.type == pygame.K_RIGHT or event.key == pygame.K_d:
playerMovement[0] = 2 # Set the x-velocity to the desired value.
if event.type == pygame.K_LEFT or event.key == pygame.K_a:
playerMovement[0] = -2
if event.type == pygame.KEYUP:
if event.type == pygame.K_RIGHT or event.key == pygame.K_d:
playerMovement[0] = 0 # Stop the player when the button is released.
if event.type == pygame.K_LEFT or event.key == pygame.K_a:
playerMovement[0] = 0
# Game logic.
playerRect.move_ip(playerMovement)
# Draw everything.
display.fill((214, 42, 78))
tileRect = []
y = 0
for row in level:
x = 0
for col in row:
if col == '2':
display.blit(grass, (x*16, y*16))
if col == '1':
display.blit(dirt, (x*16, y*16))
if col != '0':
tileRect.append(pygame.Rect(x*16,y*16,16,16))
x += 1
y += 1
display.blit(player, playerRect)
windowSurface.blit(pygame.transform.scale(display, windowSize), (0, 0))
pygame.draw.rect(windowSurface, black, playerRect)
pygame.display.update()
mainClock.tick(60)
I'm here to ask what is the problem with my code? I'm making a game engine, and I thought the easiest way to sort player types would be putting them into a different script and using them there. However, I am having a slight issue doing that, and have no clue how to fix it.
Here is the error I'm getting:
Traceback (most recent call last): File "C:\Users\Harry Court\AppData\Local\Programs\Python\Python36-32\projects\Game Engine\main.py", line 48, in <module> topDownPlayerControls() NameError: name 'topDownPlayerControls' is not defined
P.S: If there is an easier way to do this, please tell me!
main.py
import pygame
from playerSelection import *
import ctypes
from ctypes.wintypes import HWND, LPWSTR, UINT
# Window Size
display_w = 1366
display_h = 768
# Initialize and Set Display
pygame.init()
gameDisplay = pygame.display.set_mode((display_w, display_h))
pygame.display.set_caption("The Joker Engine (Version Undecided) - By Harrison Court")
clock = pygame.time.Clock()
# Ctypes ID's
IDYES = 6
IDNO = 7
x = (display_w * 0.45)
y = (display_h * 0.8)
# Colours
black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0, 0)
running = True
gameDisplay.fill(white)
while running:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
# Misc.
if event.key == pygame.K_ESCAPE:
quitWindow = ctypes.windll.user32.MessageBoxW(0, "Are you sure you want to quit?", "Warning!", 4)
# Confirm they want to leave.
if quitWindow == IDYES:
quit()
topDownPlayerControls()
pygame.display.update()
clock.tick(60)
pygame.quit()
quit()
playerSelection.py:
import pygame
from tkinter import Tk, Frame, Menu
import ctypes
from ctypes.wintypes import HWND, LPWSTR, UINT
x = (300)
y = (300)
playerImg = pygame.image.load('Player.png')
class playerMovement():
def player(x,y):
gameDisplay.blit(playerImg, (x,y))
def topDownPlayerControls():
if event.type == pygame.KEYDOWN:
# Left & Right
if event.key == pygame.K_LEFT:
x_change = -5
print("Left")
elif event.key == pygame.K_RIGHT:
x_change = 5
print("Right")
# Up & Down
if event.key == pygame.K_DOWN:
y_change = 5
print("Down")
elif event.key == pygame.K_UP:
y_change = -5
print("Up")
# If no keys are pressed, do this...
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
if event.key == pygame.K_DOWN or event.key == pygame.K_UP:
y_change = 0
# Player Movement
x += x_change
y += y_change
Updated Script:
main.py:
import pygame
from playerSelection import *
from gui import *
from tkinter import *
import ctypes
from ctypes.wintypes import HWND, LPWSTR, UINT
# Define stuff
player = playerMovement()
# Window Size
display_w = 1366
display_h = 768
# Initialize and Set Display
pygame.init()
gameDisplay = pygame.display.set_mode((display_w, display_h))
pygame.display.set_caption("The Joker Engine (Version Undecided) - By Harrison Court")
clock = pygame.time.Clock()
# Ctypes ID's
IDYES = 6
IDNO = 7
x = (display_w * 0.45)
y = (display_h * 0.8)
# Colours
black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0, 0)
running = True
gameDisplay.fill(white)
# Make sure the game isn't dying on us.
while running:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
# Misc.
if event.key == pygame.K_ESCAPE:
quitWindow = ctypes.windll.user32.MessageBoxW(0, "Are you sure you want to quit?", "Warning!", 4)
# Confirm they want to leave.
if quitWindow == IDYES:
quit()
player.displayPlayer(x,y)
player.topDownPlayerControls
pygame.display.update()
clock.tick(60)
pygame.quit()
quit()
playerSelection.py:
import pygame
from tkinter import Tk, Frame, Menu
import ctypes
from ctypes.wintypes import HWND, LPWSTR, UINT
x = (300)
y = (300)
display_w = 1366
display_h = 768
gameDisplay = pygame.display.set_mode((display_w, display_h))
playerImg = pygame.image.load('Player.png')
class playerMovement():
def displayPlayer(self,x,y):
gameDisplay.blit(playerImg, (x,y))
def topDownPlayerControls(self):
if event.type == pygame.KEYDOWN:
# Left & Right
if event.key == pygame.K_LEFT:
x_change = -5
print("Left")
elif event.key == pygame.K_RIGHT:
x_change = 5
print("Right")
# Up & Down
if event.key == pygame.K_DOWN:
y_change = 5
print("Down")
elif event.key == pygame.K_UP:
y_change = -5
print("Up")
# If no keys are pressed, do this...
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
if event.key == pygame.K_DOWN or event.key == pygame.K_UP:
y_change = 0
# Player Movement
x += x_change
y += y_change
Your error message is saying that the function topDownPlayerControls is not defined. This is because you are trying to call it as a free function. However, this function is defined within the playerMovement class. So, you would first need to create a playerMovement object, and then call the topDownPlayerControls function on that object. It would look something like this:
player = playerMovement()
player.topDownPlayerControls()
It looks like you will have a number of other fails after that, but I'll leave that as an exercise :)
I am kinda stuck with a supposed to be simple code to check if the user has pressed "w" or "s".
Below you can see my code:
import pygame
pygame.init()
while True:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN and event.key == pygame.K_w:
print('Forward')
elif event.type == pygame.KEYDOWN and event.key == pygame.K_s:
print('Backward')
Am I forgetting something here?
Thanks!
A window needs to be created to receive key presses, the following works.
import pygame
import sys
pygame.init()
pygame.display.set_mode((100, 100))
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
print('Forward')
elif event.key == pygame.K_s:
print('Backward')
This is what seems to me the most simple and understandable way to do it:
import pygame
pygame.init()
pygame.display.set_mode((300, 300))
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
print('Forward')
elif event.key == pygame.K_s:
print('Backward')
Instead of using the sys.exit() method I prefer to just use pygame.quit()
it is no good to ask the gamer to keep hitting w to get the response. If you want to read the "pressed" state. You could consider the followings:
from pygame import *
import time
flag = False # The flag is essential.
DONE = False
screen = display.set_mode((500,500)) # 1180, 216
count=0
while not DONE:
event.pump() # process event queue
keys = key.get_pressed() # It gets the states of all keyboard keys.
#print("%d"%count,keys)
count+=1
if keys[ord('w')]: # And if the key is K_DOWN:
print("%d w down"%count)
if keys[ord('s')]: # And if the key is K_DOWN:
print("%d s down"%count)
time.sleep(0.1)
Try this:
import pygame
pygame.init()
key = pygame.key.get_pressed()
while True:
for event in pygame.event.get():
if event.type == KEYDOWN and event.key == pygame.K_w:
print('Forward')
elif event.type == KEYDOWN and event.key == pygame.K_s:
print('Backward')
Sample code to understand how key press events work.
import pygame
from pygame.locals import *
def main():
pygame.init()
pygame.display.set_caption("Move Box With Arrow Keys")
wndsize = (320, 240)
display = pygame.display.set_mode(wndsize)
x = 5
y = 5
black = (0, 0, 0)
white = (255, 255, 255)
rectpos = (x, y)
rectdim = (50, 50)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
x += 5
print("K_RIGHT")
if event.key == pygame.K_LEFT:
x -= 5
print("K_LEFT")
if event.key == pygame.K_UP:
y -= 5
print("K_UP")
if event.key == pygame.K_DOWN:
y += 5
print("K_DOWN")
# Don't allow coords below 0
if 0 > x:
x = 5
if 0 > y:
y = 5
# Don't allow overflow
if x + rectdim[0] > wndsize[0]:
x = wndsize[0] - rectdim[0] - 5
if y + rectdim[1] > wndsize[1]:
y = wndsize[1] - rectdim[1] - 5
rectpos = (x, y)
display.fill(white)
rect = pygame.draw.rect(display, black, ((rectpos), (rectdim)))
pygame.display.update()
main()
This might work:
from pygame import *
init()
if key.get_pressed()[K_w] == True:
print('Forwards')
if key.get_pressed()[K_s] == True:
print('Backwards')`