USB controller will not work in Pygame - python

I have a USB controller that I have mapped to be the arrow keys on the keyboard, outside of gaming programs (as in, you can use it as the normal arrow keys on the keyboard). I did this using the program ControlMK. My Pygame program will not recognize the controller as the keyboard. When I try to use the Joystick modules, the program does not function properly.
Here is my code:
import pygame, sys, time, random
from pygame.locals import *
# set up pygame
try:
pygame.init()
pygame.display.init()
pygame.mixer.init(size=8, buffer=2048)
pygame.mixer.get_init
except:
print "error in init\n"
white=(255,255,255)
screen=pygame.display.set_mode((800,600), pygame.RESIZABLE)
class Loadsound:
def __init__(self, name, key, sound_file):
self.name = name
self.name=key
self.sound = pygame.mixer.Sound(sound_file)
sound_left=[]
sound_left.append(Loadsound("left","K_LEFT", "left.wav"))
sound_right=[]
sound_right.append(Loadsound("right","K_RIGHT", "right.wav"))
sound_up=[]
sound_up.append(Loadsound("up","K_UP","up.wav"))
sound_down=[]
sound_down.append(Loadsound("down","K_DOWN","down.wav"))
while True:
for i in pygame.event.get():
if i.type==QUIT:
exit()
pressed=pygame.key.get_pressed()
if pressed[K_LEFT]:
for left in sound_left:
left.sound.play()
elif pressed[K_RIGHT]:
for right in sound_right:
right.sound.play()
elif pressed[K_UP]:
for up in sound_up:
up.sound.play()
elif pressed[K_DOWN]:
for down in sound_down:
down.sound.play()
Thank you for the help!
Edit:
I have been trying to use the Joystick module. Here is where I was taking example code from:
http://www.pygame.org/wiki/Joystick_analyzer
I edited my code to include some of it, but it still does not work. Here is my edited code:
import pygame, sys, time, random
from pygame.locals import *
from pygame import *
# set up pygame
try:
pygame.init()
pygame.display.init()
pygame.mixer.init(size=8, buffer=2048)
pygame.mixer.get_init
except:
print "error in init\n"
white=(255,255,255)
screen=pygame.display.set_mode((800,600), pygame.RESIZABLE)
class Loadsound:
def __init__(self, name, key, sound_file):
self.name = name
self.name=key
self.sound = pygame.mixer.Sound(sound_file)
sound_left=[]
sound_left.append(Loadsound("left","K_LEFT", "left.wav"))
sound_right=[]
sound_right.append(Loadsound("right","K_RIGHT", "right.wav"))
sound_up=[]
sound_up.append(Loadsound("up","K_UP","up.wav"))
sound_down=[]
sound_down.append(Loadsound("down","K_DOWN","down.wav"))
def __init__(self):
pygame.joystick.init()
self.my_joystick = None
self.joystick_names = []
for i in range(0, pygame.joystick.get_count()):
self.joystick_names.append(pygame.joystick.Joystick(i).get_name())
print self.joystick_names
if (len(self.joystick_names) > 0):
self.my_joystick = pygame.joystick.Joystick(0)
self.my_joystick.init()
#max_joy = max(self.my_joystick.get_numaxes(), self.my_joystick.get_numbuttons(), self.my_joystick.get_numhats()
while True:
for i in pygame.event.get():
pygame.event.pump()
if i.type==QUIT:
exit()
#pygame.joystick.Joystick(0)
#Joystick.init()
pressed=pygame.key.get_pressed()
#pressed_j=Joystick.get_hat()
def check_hat(self, p_hat):
if (self.my_joystick):
if (p_hat,self.my_joystick.get_numhats()):
return self.my_joystick.get_hat(p_hat)
return (0, 0)
if check_hat==(-1,0):
#if pressed[K_LEFT]:
for left in sound_left:
left.sound.play()
elif pressed[K_RIGHT]:
for right in sound_right:
right.sound.play()
elif pressed[K_UP]:
for up in sound_up:
up.sound.play()
elif pressed[K_DOWN]:
for down in sound_down:
down.sound.play()
For clarity, my code DOES work when using the keyboard. However, it does not translate to the controller which is mapped to the same keys.

You'll need to use Pygame's Joystick module, or something similar, which has method's such as: Joystick.get_init(), which tells if the joystick is initialized in Pygame, and Joystick.get_axis(axis_number) which returns the Joystick's position, as a float, along a given axis axis_number. ControlMK is likely mapping the joystick to key inputs at too high of a level to interact with Pygame, though there may be some way to change that, its documentation seems limited.

Try this:
import pygame
pygame.init()
print "Joystics: ", pygame.joystick.get_count()
my_joystick = pygame.joystick.Joystick(0)
my_joystick.init()
clock = pygame.time.Clock()
while 1:
for event in pygame.event.get():
print my_joystick.get_axis(0), my_joystick.get_axis(1)
clock.tick(40)
pygame.quit ()

Related

How to integrate 'MENU' code for my game with the actual gaming code?

I have created a basic game. Now I want to expand on the basic game and add a video game menu to it. I have two programs:
Basic game code
MENU code
I want to integrate both codes into one so that my game becomes more functional. I am just a beginner and need directions on how to do that. Thanks for helping.
BASIC GAME CODE:
import pygame
import random
import sys
pygame.init()
w=800
h=600
red=(251,63,75)
blue=(104,41,171)
yellow=(255,255,0)
player_size=25
player_pos=[w/2,h-(2*player_size)]
enemy_size=25
enemy_pos=[random.randint(0,w-enemy_size),0]
enemy_list=[ ]
bg_color=(0,0,0)
screen=pygame.display.set_mode((w,h))
game_over=False
speed=10
score=0
clock=pygame.time.Clock()
myFont=pygame.font.SysFont("monospace",35)
def set_level(score,speed):
if score<10:
speed=5
elif score<20:
speed=6
elif score<30:
speed=8
elif score<40:
speed=10
elif score<50:
speed=13
elif score<200:
speed=15
else:
speed=20
return speed
def drop_enemies(enemy_list):
delay=random.random()
if len(enemy_list)<6 and delay<0.1:
x_pos=random.randint(0,w-enemy_size)
y_pos=0
enemy_list.append([x_pos,y_pos])
def draw_enemies(enemy_list):
for enemy_pos in enemy_list:
pygame.draw.rect(screen,blue,
(enemy_pos[0],enemy_pos[1],enemy_size,enemy_size))
def update_enemy_pos(enemy_list,score):
for idx,enemy_pos in enumerate(enemy_list):
if enemy_pos[1]>=0 and enemy_pos[1]<h:
enemy_pos[1]+=speed
else:
enemy_list.pop(idx)
score+=1
return score
def detect_collision(player_pos,enemy_pos):
p_x=player_pos[0]
p_y=player_pos[1]
e_x=enemy_pos[0]
e_y=enemy_pos[1]
if (e_x>=p_x and e_x<(p_x+player_size)) or (p_x>=e_x and p_x<(e_x+enemy_size)):
if (e_y>=p_y and e_y<(p_y+player_size)) or (p_y>=e_y and p_y<(e_y+enemy_size)):
return True
return False
def collision_check(enemy_list,player_pos):
for enemy_pos in enemy_list:
if detect_collision(enemy_pos,player_pos):
return True
return False
while not game_over:
for event in pygame.event.get():
if event.type==pygame.QUIT:
sys.exit()
if event.type==pygame.KEYDOWN:
x=player_pos[0]
y=player_pos[1]
if event.key==pygame.K_LEFT:
x-=player_size
elif event.key==pygame.K_UP:
y-=player_size
elif event.key==pygame.K_RIGHT:
x+=player_size
elif event.key==pygame.K_DOWN:
y+=player_size
player_pos=[x,y]
screen.fill(bg_color)
drop_enemies(enemy_list)
score=update_enemy_pos(enemy_list,score)
speed=set_level(score,speed)
text='Your Score is:' + str(score)
label=myFont.render(text,1,yellow)
screen.blit(label,(w/2,h-40))
if collision_check(enemy_list,player_pos):
game_over=True
break
draw_enemies(enemy_list)
pygame.draw.rect(screen,red,
(player_pos[0],player_pos[1],player_size,player_size))
clock.tick(30)
pygame.display.update()
pygame.display.flip()
GAME MENU CODE:
import pygame
import random
import sys
pygame.init()
w=800
h=600
bg_color=(34,139,34)
red=(255,0,0)
blue=(0,0,125)
bright_blue=(0,0,255)
font_size=35
b1_pos=[w/2-50,h/2]
b1_size=[105,50]
screen=pygame.display.set_mode((w,h))
myFont=pygame.font.SysFont("freesansbold.tff",font_size)
def button(b1_pos,b1_size):
mouse_pos=pygame.mouse.get_pos()
click=pygame.mouse.get_pressed()
if (b1_pos[0]<mouse_pos[0]<(b1_pos[0]+b1_size[0])) and (b1_pos[1]<mouse_pos[1]<(b1_pos[1]+b1_size[1])):
pygame.draw.rect(screen,bright_blue,(b1_pos[0],b1_pos[1],b1_size[0],b1_size[1]))
if click[0]==1:
print("Left click")
else:
pygame.draw.rect(screen,blue,(b1_pos[0],b1_pos[1],b1_size[0],b1_size[1]))
text='START'
label=myFont.render(text,1,red)
screen.blit(label,(w/2-38,h/2+5))
game_over=False
while not game_over:
for event in pygame.event.get():
if event.type==pygame.QUIT:
sys.exit()
screen.fill(bg_color)
button(b1_pos,b1_size)
pygame.display.update()
When creating a game you need something called The MainLoop. All the code that needs to be updated in every frame goes inside this loop. This loop runs forever until the game is terminated. Check these video tutorials and this
Let me give you an example:
import pygame
#Import literals such as QUIT
from pygame.locals import *
pygame.init()
w = 800
h = 600
screen = pygame.display.set_mode((w,h))
running = True
def MenuCode():
pass
def GameCode():
pass
#This is the Game Loop.
while running:
#Events are used to check if a key has
#been pressed or a mouse button or a mouse movement.
for event in pygame.event.get():
#If the user pressed the x button.
#terminate the while loop.
if event.type == QUIT:
running = False
break;
#In every frame you must clean the window with a color
#in order to draw anythin else above it.
screen.fill((0,0,0))
#Here draw anything you like
#Also somewhere here call all the code that needs to be
#called every frame (Menu code, Game code, etc)
MenuCode()
GameCode()
#Lastly you must update the display.
#The most important thing that this does
#is called buffer swapping, check it out.
pygame.display.update()
#When the loop terminates, terminate pygame.
pygame.quit()
If you want to learn what the update() method does check about double buffering

Attribute error : RPi.GPIO.PWM has no attribute 'ChangeDutyCycle'

So i'm making a little robot using a raspberry pi B+ , everything is going fairly nicely, but I get this error message that I don't seem to be able to solve ..
Attribute error : RPi.GPIO.PWM has no attribute 'ChangeDutyCycle'
Here's two things you might need to know : :D
- The code worked perfectly before I put it as a class, ChangeDutyCycle DOES exist
- If I put my mouse in an 'unallowed' i.e. which gives ChangeDutyCycle a value less than 0 or more than 100, the error changes and becomes 'ChangeDutyCycle can't accept value less than 0 or more than 100' (So first you tell me there is no such function, and then tell me it can't have some values? :roll: )
So I'm going slightly crazy now.
Note : I'm a complete beginner in python, and honestly, it seems to me like a bad version of java, but the RPi GPIO seems to be optimised for this language so I'm trying it out, so if you see any other mistake or bad things, do let me know :D
The code now :
My 'main', where I take input from a pygame window (position of mouse)
#!/usr/bin/python
# -*- coding: utf-8 -*-
import pygame
import RPi.GPIO as GPIO
from pygame.locals import *
from control import control
print('Path :', pygame.__file__)
def main():
pygame.init()
screen = pygame.display.set_mode((200,200))
ctrl = control()
bg = pygame.Surface(screen.get_size())
bg = bg.convert()
bg.fill((250,250,250))
font = pygame.font.Font(None, 36)
text = font.render("Hello", 1, (10,10,10,))
textpos = text.get_rect()
textpos.centerx = bg.get_rect().centerx
bg.blit(text, textpos)
screen.blit(bg, (0,0))
pygame.display.flip()
try:
while 1:
for event in pygame.event.get():
bg.fill((250, 250, 250))
if event.type == QUIT:
return
pos = pygame.mouse.get_pos()
x = pos[0]-100
y = -(pos[1]-200)-100
text = font.render(str(x)+' '+str(y), 1, (10,10,10,))
ctrl.updateEngine(x,y)
bg.blit(text,textpos)
screen.blit(bg, (0,0))
pygame.display.flip()
except KeyboardInterrupt:
return
finally:
ctrl.cleanup()
if __name__ == '__main__': main()
And my class with functions to control motors , control.py :
import RPi.GPIO as GPIO
from time import sleep
import sys
import Tkinter as tk
class control:
def __init__(self):
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(3, GPIO.OUT)# set GPIO 25 as output for white led
GPIO.setup(18, GPIO.OUT)# set GPIO 24 as output for red led
GPIO.setup(2, GPIO.OUT)
GPIO.setup(17, GPIO.OUT)
self.Rb = GPIO.PWM(2, 100)
self.Lf = GPIO.PWM(18, 100)
self.Lb = GPIO.PWM(17, 100)
self.Rf = GPIO.PWM(3, 100)
self.Rb.start(0)
self.Rf.start(0)
self.Lb.start(0)
self.Lf.start(0)
def cleanup(self):
self.Rb.stop()
self.Rf.stop()
self.Lb.stop()
self.Lf.stop()
def updateEngine(self, x, y):
self.clear()
if y>15 and (x>15 or x<-15) :
self.Rf.ChangeDutyCucle(y-15-x)
self.Lf.ChangeDutyCycle(y-15+x)
elif y<-15 and (x>15 or x<-15) :
self.Rb.ChangeDutyCycle(-15-y-x)
self.Lb.ChangeDutyCycle(-15-y+x)
def clear(self):
self.Rf.ChangeDutyCycle(0)
self.Rb.ChangeDutyCycle(0)
self.Lf.ChangeDutyCycle(0)
self.Lb.ChangeDutyCycle(0)
So the error happens in control.py, at the updateEngine method.
Also you'll note I imported an amazing number of 3 times the same package (RPi.GPIO) cause I'm not sure where to import it ! :)
Any help would be graciously accepted :)
I tracked down my issue to a typo: My updateEngine function had a call to self.Rf.ChangeDutyCucle, when it should have been self.Rf.ChangeDutyCycle.

Python Basic control flow errors

When I run this code, it enters a while loop and checks every turn whether or not on_title_screen==True. If it is true, the program will continue to check for input, but if it is false, the loop will refresh the screen and begin the game. However, when start is clicked, and on_title_screen=False, the game still captures mouse input, and does not display the bird that it should.
import random
import pygame
from pygame import *
import math
import sys
#Presets for window
size=width,height=500,500
Ag=-9.80665
clock = pygame.time.Clock()
white=(255,255,255)
blue=(0,0,255)
red=(255,0,0)
gray_bgColor=(190,193,212)
#Initialise pygame Surface as screen
pygame.init()
pygame.font.init()
screen=pygame.display.set_mode(size)
pygame.display.set_caption("Flappy Kid")
#Game Presets
vY=0
xPos,yPos=200,100
score=0
on_title_screen=True
def falling_loop():
for event in pygame.event.get():
if event.type==pygame.KEYDOWN:
if event.key==pygame.K_UP:
vY=-10
if yPos>height-50:
yPos=100
vY+=1
yPos+=vY
class graphics():
#Holds the methods for loading/displaying graphics
def load_images(self):
#Loads the background and sprite images
self.background_image=pygame.image.load("flappy_background.png").convert()
self.bird_image=pygame.image.load("flappy_sprite.jpg").convert()
screen.set_colorkey(white)
self.birdHitBox=self.bird_image.get_rect()
def show_background(self):
#blits the background
screen.blit(self.background_image,[0,0])
def refresh_display(self):
#updates the display
screen.blit(self.background_image,[xPos,yPos],self.birdHitBox)
falling_loop()
screen.blit(self.bird_image,[xPos,yPos])
class titleScreen():
#Holds the methods for the title screen/menu
def title(self):
#Sets up the title
titleText="Flappy Game"
titlePos=(0,0)
currentFont=pygame.font.SysFont("arialms",30,bold=True,italic=True)
renderTitle=currentFont.render(titleText,1,blue,gray_bgColor)
self.titlex,self.titley=currentFont.size(titleText)
screen.blit(renderTitle,titlePos)
def start(self):
#Sets up the start Button
startText="Start Game"
self.startPos=(0,self.titley)
currentFont=pygame.font.SysFont("arialms",25,bold=False,italic=False)
renderStart=currentFont.render(startText,1,blue,gray_bgColor)
self.startx,self.starty=currentFont.size(startText)
self.start_rect = pygame.Rect(self.startPos[0],self.titley,self.startx,self.starty)
screen.blit(renderStart,self.startPos)
def quit(self):
#Sets up the quit button
quitText="Quit"
self.quitPos=(0,self.starty+self.titley)
currentFont=pygame.font.SysFont("arialms",25,bold=False,italic=False)
renderQuit=currentFont.render(quitText,1,red,gray_bgColor)
self.quitx,self.quity=currentFont.size(quitText)
self.quit_rect = pygame.Rect(self.quitPos[0],self.titley+self.starty,self.quitx,self.quity)
screen.blit(renderQuit,self.quitPos)
def get_click(self):
#Gets mouse click and processes outcomes
for event in pygame.event.get():
if event.type==pygame.MOUSEBUTTONDOWN:
x,y=pygame.mouse.get_pos()
#Tests for start:
if self.start_rect.collidepoint(x,y):
print("start")
on_title_screen=False
elif self.quit_rect.collidepoint(x,y):
print("quit")
sys.exit()
titleC=titleScreen()
graphicsC=graphics()
def setupTitle():
#bundles all title_screen functions
titleC.title()
titleC.start()
titleC.quit()
def main():
graphicsC.load_images()
graphicsC.show_background()
setupTitle()
while True:
clock.tick(30)
if on_title_screen==False:
graphicsC.refresh_display()
elif on_title_screen==True:
titleC.get_click()
pygame.display.flip()
main()
I think #TessellatingHeckler is right, on_title_screen is a shadow variable, not the same.
In this code, there is nowhere that on_title_screen (global) could ever be set to False.
A more powerful answer though is to explain how to find the problem. I strongly recommend using pdb or ipdb. In this case, I would put one just inside of the while loop and make sure that the variables are what I think they should be.

When I try multiprocessing, multiple windows show up

I'm trying to create a pong game for my first Pygame game. I'm very new to Pygame and relatively new to Python. So far I only have the two bumpers on either side. Here is the code I have so far:
import pygame, sys, os
from pygame.locals import *
from multiprocessing import Process
window = pygame.display.set_mode((600,400))
pygame.display.set_caption("Pong")
screen = pygame.display.get_surface()
pongBackground = pygame.image.load("C:/Users/LN/Desktop/PongBackground.png")
pongHitter = pygame.image.load("C:/Users/LN/Desktop/PongHitter.png")
pongHitter = pygame.image.load("C:/Users/LN/Desktop/PongHitter.png")
pongBall = pygame.image.load("C:/Users/LN/Desktop/PongBall.png")
pygame.init()
class hitter():
"""moves the pong hitter with arrow keys"""
def _init_(self):
screen.blit(pongBackground, (0,0))
self.position = pongHitter.get_rect()
pygame.display.update()
def goTo(self, coord):
screen.blit(pongHitter,coord)
self.position = self.position.move(coord)
pygame.display.update()
def moveUp(self):
for i in range(1):
screen.blit(pongBackground, self.position, self.position)
self.position = self.position.move(0, -1)
screen.blit(pongHitter, self.position)
pygame.display.update()
pygame.time.delay(10)
def moveDown(self):
for i in range(1):
screen.blit(pongBackground, self.position, self.position)
self.position = self.position.move(0, 1)
screen.blit(pongHitter, self.position)
pygame.display.update()
pygame.time.delay(10)
hitterA=hitter()
hitterB=hitter()
hitterA._init_()
hitterB._init_()
hitterA.goTo((5,200))
hitterB.goTo((590,200))
pygame.key.set_repeat(1,1)
contin=True
def inputLeft():
while True:
for event in pygame.event.get():
if pygame.key.get_pressed()[K_UP]:
hitterA.moveUp()
elif pygame.key.get_pressed()[K_DOWN]:
hitterA.moveDown()
elif pygame.key.get_pressed()[K_ESCAPE]:
sys.exit(0)
def inputRight():
while True:
for event in pygame.event.get():
if pygame.key.get_pressed()[K_w]:
hitterB.moveUp()
elif pygame.key.get_pressed()[K_s]:
hitterB.moveDown()
elif pygame.key.get_pressed()[K_ESCAPE]:
sys.exit(0)
if __name__=='__main__':
p = Process(target=inputLeft)
p.start()
p.join()
p2 = Process(target=inputRight)
p2.start()
p2.join()
Now I'm trying to get it so that both bumpers can move simultaneously. I've tried multiprocessing as you can see above, but it creates different window with each process. How can I get everything to display on one window? Thanks! By the way, this python 3.3.
multi processing is the wrong approach
give wasd to one hitter and the arrows keys to another then for youre keypress statments make it so that wasd moves one paddle and the arrows move the other
here is what your mainloop should look like instead of having two:
while True:
for event in pygame.event.get():
if pygame.key.get_pressed()[K_UP]:
hitterA.moveUp()
if pygame.key.get_pressed()[K_DOWN]:
hitterA.moveDown()
if pygame.key.get_pressed()[K_w]:
hitterB.moveUp()
if pygame.key.get_pressed()[K_s]:
hitterB.moveDown()
if pygame.key.get_pressed()[K_ESCAPE]:
sys.exit(0)
there is no need for multiprocessing it will work just fine without it
your code looks great but just get rid of the multiprocessing
here is a pretty good example of a pong game with pygame you can use it to help you out
Pygame Pong Example

Pygame Menu: calling another .py file

I'm learning pygame by helping a friend make a Menu for his interactive TicTacToe game. It's simple enough, a title and 2 buttons for starting and exiting the game. He has the game done, I just need to link my menu to his game.
After fiddling with pygame, I finally finished making the images appear in the pygame window(I never thought that seeing text appear in a blank window for the first time could look so beautiful! T^T). I believe that the next step is to make the images act like buttons to call another python file.
Here is my simple code for the menu:
import pygame
from pygame.locals import *
from sys import exit
pygame.init()
resX, resY = 640, 480
windowObj = pygame.display.set_mode((resX,resY))
titleImg = pygame.image.load("title.png")
startImg = pygame.image.load("start.png")
exitImg = pygame.image.load("exit.png")
def width_center(img):
"""For horizontally setting an image."""
return resX/2 - x(img)/2
def height_center(img):
"""For vertically setting an image."""
return resY/2 - y(img)/2
def x(img):
"""Width of object."""
return img.get_width()
def y(img):
"""Height of object."""
return img.get_height()
while True:
pygame.display.update()
windowObj.fill((255,255,255))
windowObj.blit(titleImg,(width_center(titleImg), 30))
#This I want to link:
windowObj.blit(startImg,(width_center(startImg),height_center(startImg)-10))
windowObj.blit(exitImg,(width_center(exitImg),height_center(exitImg)+y(startImg)))
for i in pygame.event.get():
if i.type == QUIT:
exit()
Simply put, I want to know how to make the startImg call TTTClick.py. Should there also be a certain format for his TTTClick.py?
Thanks :)
If it's one project, you can have 'title screen' state, and 'game' states.
Psuedo code:
class Game():
def __init__(self):
self.done = False
self.state = "title"
def game_draw(self):
# game draw
def game_update(self):
# game event handling, and physics
def title_draw(self):
# title draw
def title_update(self):
# on event click
self.state = "game"
def loop(self):
# main loop
while not self.done:
if state == 'title':
title_update()
title_draw()
elif state == 'game':
game_update()
game_draw()
if __name__ == "__main__":
game = Game()
game.loop()
Note: x, height_center ect. already exist in pygame.Rect
# if Surface
titleImage.get_rect().width
# if Sprite
titleImage.rect.width
There's more, rect.center, rect.centerx, see the full listing at http://www.pygame.org/docs/ref/rect.html

Categories