Using functions and values from another script python 2.7 and pygame - python

So I'm trying to learn making games with python using the pygame module and coming from a javascript background I want to be able to build a program using multiple scripts. So I try to load another script and use one of its functions as well as variables declared in that script. What I want to be able to do is call the 'update' funciton from the other script but use the variables declared in this one. Any suggestions?
Edit:
Ok, so I clearly haven't clarified my question very well. Importing the script is not my problem, I can get it to import fine. The trouble I have is that after I import it I need to be able to call a function from this script from the main script that uses variables from this script.
What happens right now is that I call the update function in this script an it gives me an error that says that the variable 'animTimer' is being called before it is declared. That's what I need to fix.
import pygame, sys, time, random
from pygame.locals import *
# Create animation class
class animation2D:
"a class for creating animations"
frames = []
speed = 3
cFrame = 0
player = pygame.Rect(300, 100, 40, 40)
playerImg1 = pygame.image.load('player1.png')
playerImgS = pygame.transform.scale(playerImg1, (40,40))
playerImg2 = pygame.image.load('player2.png')
playerImg3 = pygame.image.load('player3.png')
playerImg4 = pygame.image.load('player4.png')
playerImg5 = pygame.image.load('player5.png')
playerImg6 = pygame.image.load('player6.png')
playerAnim = animation2D
playerAnim.frames = [playerImg1, playerImg2, playerImg3, playerImg4, playerImg5, playerImg6]
animTimer = 0
print(animTimer)
def Update():
# Draw Player
if animTimer < playerAnim.speed:
animTimer += 1
else:
animTimer = 0
playerImgS = pygame.transform.scale((playerAnim.frames[playerAnim.cFrame]), (40,40))
if playerAnim.cFrame < len(playerAnim.frames)-1:
playerAnim.cFrame += 1
else:
playerAnim.cFrame = 0
windowSurface.blit(playerImgS, player)
import pygame, sys, time, random
from pygame.locals import *
import animationScript
# Set up pygame
pygame.init()
mainClock = pygame.time.Clock()
# Set up window
screenW = 400
screenH = 400
windowSurface = pygame.display.set_mode((screenW, screenH), 0, 32)
pygame.display.set_caption('Sprites and sound')
# Set up the colors
black = (0,0,200)
# Set up music
pygame.mixer.music.load('testmidi.mid')
#pygame.mixer.music.play(-1,0.0)
# Run the game loop
while True:
# Check for the QUIT event
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYUP:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
# Draw the background onto the surface
windowSurface.fill(black)
# Draw Player
animationScript.Update()
# Draw the window onto the screen
pygame.display.update()
mainClock.tick(40)

EDIT: It looks to me as though you're trying to do something like this:
>>> a = 4
>>> def inca():
... a += 1
...
>>> inca()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in inca
UnboundLocalError: local variable 'a' referenced before assignment
when you should be passing in parameters, like this:
>>> def inc(n):
... return n + 1
...
>>> a = 4
>>> a = inc(a)
>>> a
5
Python doesn't like to clutter up the global namespace. This is a good thing, I promise! Make sure you assign the variable to the result of the function, as I did on the line a = inc(a). Otherwise, you would have to muck around with global variables, which isn't very good practice.
In your case, Update() should take the parameters it wishes to modify, and return their new values.
You can import this module into the other script. This will allow you to access all module-level functions, variables, etc, using the syntax
mymodulename.functionname()
or
mymodulename.varname.
If you want to access something within a class within a module, the same syntax still works!
mymodulename.classname.classmember
For example:
####file_a.py####
import file_b
print file_b.message
c = file_b.myclass()
c.helloworld()
####file_b.py####
message = "This is from file b"
class myclass:
def helloworld(self):
print "hello, world!"
#################
$ python file_a.py
This is from file b
hello, world!
If your modules aren't in the same directory, you will need to add the directory from which you would like to import to your path. However, I would recommend leaving them in the same directory for now, as you seem to be learning Python.

You can use import, but will need to either add the path to your script to your PYTHONPATH environment variable or a line of code before the import as follows:
sys.path.insert(0, path_to_your_script_here)
You can then either import the whole module using:
import module name
and reference the functions with module.function() or you can import specific functions, tehn ou just call the function name directly:
from module import function

Related

Is there any way to import a variable from a function in another file without using return in Python?

I have this pygame code which is divided into multiple files and in one of the files I want to import a variable from a function which is in another file.
# gamescreen.py
highscore = 0
def game_screen(screen):
...
hits = pygame.sprite.spritecollide(player, world_sprites, True, pygame.sprite.collide_mask)
if len(hits) > 0:
if score > highscore:
global highscore
highscore = score
state = PLAYAGAIN
...
return state
# playagain.py
def play_again(screen):
...
highscore_texto = font.render('highscore: {0}'.format(highscore), True, (BLACK))
background.blit(highscore_texto, (30, 25))
...
Is there any way I can acess that highscore variable in the file playagain.py without having to return it in the game_screen function?
When I tried to return it in the game_screen function like this:
return state, highscore
And access it in the playagain.py file like this:
game_screen(screen)[1]
It just ran the game_screen function two times, which is not what I want because it messes up my game.
import gamestream
print(gamestream.highscore)
The variable is set in the module namespace (confusingly named "global" when its really "module global"). Import the module and you've got its namespace.
This doesn't work
from gamestream import highscore
In that case you rebound the current thing in highscore to your module's namespace and it won't see changes to the original. It is the same as if you had done
import gamestream
highscore = gamestream.highscore
A new variable called "highscore" is created in the local module and the current value in gamestream.highscore is bound to it. If gamestream.highscore is reassigned, that wouldn't affect this separate variable.

TypeError: 'pygame.Surface' object is not callable [Pygame module]

I have been designing a game recently as I'm starting a course at school
and thought it would be helpful to get ahead.
I encountered the error
Traceback (most recent call last):
File "C:\Users\Jake\Documents\Dungeon Crawler 2.1\Main.py", line 100, in <module>
town()
File "C:\Users\Jake\Documents\Dungeon Crawler 2.1\Main.py", line 85, in town
houseSpr1(0,250)
TypeError: 'pygame.Surface' object is not callable
While executing this code.
def town ():
global outTown
while not outTown:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
print (event)
mx, my = pygame.mouse.get_pos()
mx = mx + my
if 375 <= mx <= 448:
outTown = True
print ("OK!")
if event.type == pygame.QUIT:
pygame.quit()
quit()
houseSpr1 = pygame.image.load ('houseD.png') # default house img
houseSpr1(0,250)
gameDisplay.fill(green) # background
pygame.draw.rect(gameDisplay,grey,(0,400,1280,50)) # main path
pygame.draw.rect(gameDisplay,grey,(200,125,50,280)) # branch path
player(x,y)
pygame.display.update()
clock.tick(60)
def houseSpr1(a,b):
gameDisplay.blit(houseSpr1, (0,250))
def house1():
global outHouse
while not outHouse:
gameDisplay.fill(black)
town()
houseSpr1()
gameIntro()
house1()
pygame.quit()
quit()
I understand this code may be inefficient in some ways, and I would be happy to know how I can improve it as well if you wish to provide insight in that light.
Any help with this error would be appreciated. And yes, I have read the rest of the questions before mine and I saw it was mostly down to typographical errors, but I can not see any of those here.
You used the name houseSpr1 for two things:
A global function, def houseSpr1(a,b): ...
A local variable for an image you load: houseSpr1 = pygame.image.load ('houseD.png').
The two names are not independent. Functions are just another type of object in Python, and they are just stored like any other variable.
The moment you use the expression houseSpr1(0,250), Python sees this as:
Load the object named houseSpr1
Take the results from 0 and 250 (two integer objects)
Call the object loaded in step 1, passing in the results of step 2.
Because you assigned something to the name houseSpr1 in your town() function, it is that object, the image loaded, that Python tries to call. PyGame uses an object type named Surface to load images, and the error tells you you tried to call that object, but that object doesn't support being called.
The solution is to not use the same name:
houseSpr1Image = pygame.image.load('houseD.png')
houseSpr1(0, 250)
You'll have to adjust your houseSpr1 function too:
def houseSpr1(a,b):
gameDisplay.blit(houseSpr1Image, (0,250))
You still have other problems here; houseSpr1Image is not a global, so the houseSpr1() function won't find it, giving you a NameError exception. You are also ignoring the a and b arguments to the function, hardcoding the 0,250 there. You'll have to solve those issues to for the code to work. Perhaps you can take a 3rd parameter, image:
def houseSpr1(image, a, b):
gameDisplay.blit(image, (a, b))
and pass in the image surface:
houseSpr1Image = pygame.image.load('houseD.png')
houseSpr1(houseSpr1Image, 0, 250)
Martijn Pieters has already explained thoroughly why your code doesn't work. Here's a working, simplified version of your program to show you how it should look like.
Actually, the blit_houseSpr1 function is not necessary, since you could as well call gameDisplay.blit(houseSpr1, (80, 250)) in the main loop, but I just wanted to demonstrate how you can use a function and pass some arguments to it.
import pygame
pygame.init()
gameDisplay = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
green = pygame.Color('green4')
grey = pygame.Color('grey50')
# Load the images once, because loading them from the hard disk is slow.
# And use the convert or convert_alpha methods to improve the performance.
houseSpr1 = pygame.image.load('houseD.png').convert()
def town():
outTown = False
while not outTown:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
mx, my = pygame.mouse.get_pos()
mx = mx + my
if 375 <= mx <= 448:
outTown = True
elif event.type == pygame.QUIT:
outTown = True
gameDisplay.fill(green) # background
pygame.draw.rect(gameDisplay,grey,(0,400,1280,50)) # main path
pygame.draw.rect(gameDisplay,grey,(200,125,50,280)) # branch path
# Pass the image and the coordinates to the function.
blit_houseSpr1(houseSpr1, 80, 250)
pygame.display.update()
clock.tick(60)
def blit_houseSpr1(image, a, b):
# Now use the passed image and coordinates.
gameDisplay.blit(image, (a, b))
town()
pygame.quit()

Pyglet Player.seek() function not working?

I am trying to build a simple media tool in Pyglet, which requires a seek feature. Files are loaded, paused, and then told to seek to a specific time; however, the file does not seek when Player.seek() is called. Below is the test code I am using:
import os
import pyglet
from os.path import abspath, isfile
def loadsong(filename):
# check for file
print("Attempting to load "+filename)
filename = abspath(filename)
if not ( isfile(filename) ):
raise Exception(filename+" not found.")
# create a player for this file
song = pyglet.media.load(filename)
source = song.play()
source.eos_action = source.EOS_LOOP
source.pause()
return source
music = loadsong("test.mp3")
music.seek(57)
music.play()
pyglet.app.run()
What am I doing wrong here? I am using Python 3.5.2, Pyglet 1.2 alpha 1, and AVBin 11 alpha 4.
First of all, the error you're getting is quite important.
But I'll assume it's a Segmentation fault (core dumped) on the row:
music.seek(12)
Another quick note, fix your indentation! You're using 3 spaces and whether you are a space guy or a tab guy - 3 spaces is just odd -
The reason for you getting a segmentation fault when trying to seek is most likely because of AVbin, it's an old (and dead afaik) project.
I hacked together something more similar to a music player and here's an example on how you can use Seek with wav files:
import pyglet
from pyglet.gl import *
from os.path import abspath, isfile
pyglet.options['audio'] = ('pulseaudio', 'alsa', 'openal', 'silent')
pyglet.have_avbin=False
key = pyglet.window.key
def loadsong(filename):
# check for file
filename = abspath(filename)
# create a player for this file
player = pyglet.media.Player()
player.queue(pyglet.media.load(filename, streaming=False))
#player.play()
#song.eos_action = song.EOS_LOOP
#song.pause()
return player
class main(pyglet.window.Window):
def __init__ (self):
super(main, self).__init__(300, 300, fullscreen = False)
self.alive = 1
self.player = loadsong('./test.wav')
def on_draw(self):
self.render()
def on_close(self):
self.alive = 0
def on_key_press(self, symbol, modifiers):
if symbol == key.ESCAPE: # [ESC]
self.alive = 0
elif symbol == key.SPACE:
if self.player.playing:
self.player.pause()
else:
self.player.play()
elif symbol == key.RIGHT:
print('Skipping to:',self.player.time+2)
self.player.source.seek(self.player.time+2)
elif symbol == key.LEFT:
print('Rewinding to:',self.player.time-2)
self.player.source.seek(self.player.time-2)
def render(self):
self.clear()
#source = pyglet.text.Label(str(self.player.source.info.title.decode('UTF-8')), x=20, y=300-30)
volume = pyglet.text.Label(str(self.player.volume*100)+'% volume', x=20, y=40)
p_time = pyglet.text.Label(str(self.player.time), x=20, y=20)
#source.draw()
volume.draw()
p_time.draw()
self.flip()
def run(self):
while self.alive == 1:
self.render()
# -----------> This is key <----------
# This is what replaces pyglet.app.run()
# but is required for the GUI to not freeze
#
event = self.dispatch_events()
x = main()
x.run()
A few important notes:
pyglet.have_avbin=False
This will turn off AVbin completely, there is probably a way to turn it off for individual sources.. But since I rarely play around with it I honestly have no idea of how to.. So off it goes :)
Secondly:
streaming=False
On the media.load() call is quite important, otherwise you might get weird artifacts in your sound and or no sound at all. I got instance to a super high pitched scratching noise that almost made me deaf without that flag.
Other than that, the code is quite straight forward.
self.player.source.seek(<time>)
Is called on the player object that is a instance of pyglet.media.Player(). And it works brilliantly.
Another work-around would be to manually install AVbin 7 which appears to be working better, but I'm reluctant to install it on this machine just for testing purposes.. But the overall info i've gathered over the years is that that old library works better with Mp3 files.
Please ensure Player.playing is True before invoking Player.seek().
In the end of loadsong() function, you invoked the pause() that will set the Player.playing to False.
you could try:
music.play()
music.seek(57)
instead of:
music.seek(57)
music.play()
The following example uses pyglet 1.5.6, the seek() function works on my macbook pro, but negative on my windows 10:
import pyglet
from pyglet.window import key
source = pyglet.media.load(VIDEO_FILE_PATH)
fmt = source.video_format
player = pyglet.media.Player()
player.queue(source)
player.play()
window = pyglet.window.Window(width=fmt.width, height=fmt.height)
#window.event
def on_draw():
player.get_texture().blit(0, 0)
#window.event
def on_key_press(symbol, modifiers):
if symbol == key.LEFT:
player.seek(player.time - 3.5)
elif symbol == key.RIGHT:
player.seek(player.time + 3.5)
elif symbol == key.SPACE:
if player.playing:
player.pause()
else:
player.play()
pyglet.app.run()

Syntax Error; Python game spits out super method and imports

I made classes for what will basically become a BreakOut game, but I keep getting error messages. The nature of which always seem to surround two things; Class imports and the infamous "super" method. Usually in the form of a syntax error
I had some questions shot down in the past, so I will try to be as clear as I possibly can.
The main code for the game is as such...
import pygame
from Game import *
from Game.Scenes import *
from Game.Shared import *
class BreakOut:
def __init__(self):
self.__lives = 5
self.__score = 0
self.__level = Level(self)
self.__level.load(0)
self.__pad = Pad((0,0), 0)
self.__balls = [Ball((0,0), 0, self)]
pygame.init()
pygame.mixer.init()
pygame.display.set_caption("This is the Title of the Game")
self.__clock= pygame.time.Clock()
self.screen = pygame.display.set_mode(GameConstants.SCREEN_SIZE, pygame.DOUBLEBUF, 32)
pygame.mouse.set_visible(0)
self.__scenes = (
PlayingGameScene(self),
GameOver(self),
HighScoreScene(self),
MenuScene(self)
)
self.__currentScene = 0
self.__sounds = ()
def start(self):
while 1:
self.__clock.tick(100)
self.screen.fill((0,0,0))
currentScene = self.__scenes[self.__currentScene]
currentScene.handleEvents(pygame.event.get())
currentScene.render()
pygame.display.update()
def changeScene(self, scene):
pass
def getLevel(self):
pass
def getScore(self):
pass
def increaseScore(self, score):
pass
def getLives(self):
pass
def getBalls(self):
pass
def getPad(self):
pass
def playSound(self, soundClip):
pass
def reduceLives(self):
pass
def increaseLives(self):
pass
def reset (self):
pass
BreakOut().start()
At this stage, its only supposed to return a black screen, but instead it keeps giving me a error message with this traceback:
Traceback (most recent call last):
File "/Users/Ryan/PycharmProjects/Demo 1/Game/BreakOut.py", line 3, in <module>
from Game import *
File "/Users/Ryan/PycharmProjects/Demo 1/Game/__init__.py", line 9, in <module>
from Game.BreakOut import BreakOut
File "/Users/Ryan/PycharmProjects/Demo 1/Game/BreakOut.py", line 4, in <module>
from Game.Scenes import *
File "/Users/Ryan/PycharmProjects/Demo 1/Game/Scenes/__init__.py", line 3, in <module>
from Game.Scenes.HighScoreScene import HighScoreScene
File "/Users/Ryan/PycharmProjects/Demo 1/Game/Scenes/HighScoreScene.py", line 7
SyntaxError: invalid syntax
The bottom one connects to another class of code that looks like this:
from Game.Scenes.Scene import Scene
class HighScoreScene(Scene):
def __init__(self, game):
super(HighScoreScene, self.__init__(game)
PyCharm seems to highlight "super" and tells me "Old-style class contains call for super method" I don't know if that's important or not, but its something I've noticed consistently throughout the code.
I'm pretty sure its a simple mistake. Might be a typo, but I can't pinpoint it for the life of me. Please help!
super(HighScoreScene, self.__init__(game) # <- missing paren
It should be super(HighScoreScene, self).__init__(game)
And use object class BreakOut(object) if you want to use super.
New-style and classic classes
Your class Breakout line is not in line with the rest of your program (ahead by one space). If you backspace that line by one, everything should be fine (including #Padraic Cunningham 's answer).

can't get this python program to work [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 3 years ago.
Improve this question
This is the vector2 module:
class Vector2(object):
"this calculates the vector between two points"
def __init__(self , x = 0.0, y = 0.0):
self.x = x
self.y = y
def __str__(self):
return "( %s,%s )"%(self.x, self.y)
#classmethod
def from_points(cls,p1,p2):
return cls(p2[0]-p1[0],p2[1]-p1[1])
#the magnetude of a vector is the distance between two points
def get_magnetude(self):
return math.sqrt(self.x**2+self.y**2)
def normalize(self):
magnetude = self.get_magnetude()
self.x /= magnetude
self.y /= magnetude
#rhs stands for right hand side
def __add__(self,rhs):
return Vector2(self.x + rhs.x,self.y+rhs.y)
def __sub__(self,rhs):
return Vector2(self.x-rhs.x,self.y-rhs.y)
def __neg__(self):
return Vector2(-self.x, -self.y)
def __mul__(self,scalar):
return Vector2(self.x*scalar,self.y*scalar)
def __div__(self,scalar):
return Vector2(self.x /scalar, self.y/scalar)
And this is the main program, which imports vector2:
background_image_file = 'download.jpeg'
sprite_image_file = 'images.jpeg'
import math
import pygame
from pygame.locals import*
from sys import exit
import vector2
pygame.init()
screen = pygame.display.set_mode((640,480), 0 ,32)
background = pygame.image.load(background_image_file).convert()
sprite = pygame.image.load(sprite_image_file).convert_alpha()
clock = pygame.time.Clock()
position = Vector2(100.0, 100.0)#the starting point coordonates
heading = Vector2()#a vector without its magnetude(unit vector)
speed = 250.0
running = True
while running:
for event in pygame.event.get():
if event.type == QUIT:
exit()
if event.type == MOUSEBUTTONDOWN:
destination_x = event.pos[0]-sprite.get_width()/2
destination_y =event.pos[1]-sprite.get_height()/2
destination = (destination_x, destination_y)
heading = Vector2.get_magnetude(position,destination)#
heading.normalize()#a vector without magnetude,just direction
screen.blit(background, (0,0))
screen.blit(sprite, position)
time_passed = clock.tick()
time_passed_seconds = time_passed / 1000.0
distance_moved = time_passed_seconds * speed
position += (heading * distance_moved)
pygame.display.update()
I am learning Python and pygame by my self with (Beginning Game Development with Python and Pygame - From Novice to Professional (2007)) and I can't get the program to work. Also can someone please explain to me why the author use position = Vector2(100.0,100.0) and position = Vector2() to create new vectors?
It keeps saying :
traceback (most recent call last):
File "/home/moussa/Documents/python /vector_movement.py", line 21, in <module>
position = Vector2(100.0, 100.0)#the starting point coordonates
NameError: name 'Vector2' is not defined
I'm guessing that the code in the question is actually split between two files, one with the Vector2 class (in vector2.py) and the rest in some other file (which imports vector2).
The issue you're running into is that you're not accessing the class correctly. In your main module, you need to use vector2.Vector2 to access the class within its module.
Or, if you'd prefer to have easier access to the class, you could instead change your import from import vector2 to from vector2 import Vector2. This puts the class into the main module's namespace, so you can access it directly as Vector2.
As for the use of position = Vector2(100.0,100.0), this is a call to the Vector2 class's constructor. It creates an instance of the class, initializes it with the values 100 for x and 100 for y, and then binds it to the variable position. You can then use the various methods and operators that the class defines to update the instance, or get new values. For instance, the later line position += (heading * distance_moved) first multiplies the vector heading by the scalar distance_moved, then adds the vector result to position. You could do this with values in lists or tuples, but it would be much more complicated (you'd need to add and multiply the components of the vectors yourself).

Categories

Resources