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).
Related
I want to build some visualizations for searching algorithms (BFS, A* etc.) within a grid.
My solution should show each step of the algorithm using CodeSkulptor simplegui (or the offline version using SimpleGUICS2Pygame.)
I've made a version which highlights all the cells visited by changing their color, but I've run into trouble trying to make the path display step-by-step with a time delay between each step.
I've extracted the essence of the problem and created a minimal example representing it in the code below, also run-able online here: http://www.codeskulptor.org/#user47_jB2CYfNrH2_2.py
What I want is during the change_colors() function, for there to be a delay between each iteration.
CodeSkulptor doesn't have time.sleep() available, and I don't think it would help anyway.
CodeSkulptor does have timers available, which might be one solution, although I can't see how to use one in this instance.
Code below:
import time
try:
import simplegui
except ImportError:
import SimpleGUICS2Pygame.simpleguics2pygame as simplegui
simplegui.Frame._hide_status = True
TITLE = "TEST"
FRAME_WIDTH = 400
FRAME_HEIGHT = 400
DELAY = 10
class Square:
"""This class represents a simple Square object."""
def __init__(self, size, pos, pen_size=2, pen_color="red", fill_color="blue"):
"""Constructor - create an instance of Square."""
self._size = size
self._pos = pos
self._pen_size = pen_size
self._pen_color = pen_color
self._fill_color = fill_color
def set_color(self, color):
self._fill_color = color
def get_color(self):
return self._fill_color
def is_in(self, pos):
"""
Determine whether coordinates are within the area of this Square.
"""
return self._pos[0] < pos[0] < self._pos[0] + self._size and self._pos[1] < pos[1] < self._pos[1] + self._size
def draw(self, canvas):
"""
calls canvas.draw_image() to display self on canvas.
"""
points = [(self._pos[0], self._pos[1]), (self._pos[0] + self._size, self._pos[1]),
(self._pos[0] + self._size, self._pos[1] + self._size), (self._pos[0], self._pos[1] + self._size)]
canvas.draw_polygon(points, self._pen_size, self._pen_color, self._fill_color)
def __str__(self):
return "Square: {}".format(self._pos)
def draw(canvas):
for square in squares:
square.draw(canvas)
def change_colors():
for square in squares:
# time.sleep(1) # Not implemented in CodeSkulptor and would'nt work anyway
square.set_color("green")
frame = simplegui.create_frame(TITLE, FRAME_WIDTH, FRAME_HEIGHT)
frame.set_draw_handler(draw)
width = 20
squares = []
for i in range(10):
squares.append(Square(width, (i * width, 0)))
change_colors()
frame.start()
Any help appreciated.
Yes, you need to use a timer. Something like this:
I = 0
def change_next_color():
if I < len(squares):
squares[I].set_color("green")
global I
I += 1
timer = simplegui.create_timer(1000, change_next_color)
timer.start()
http://www.codeskulptor.org/#user47_udyXzppCdw2OqdI.py
I also replaced
simplegui.Frame._hide_status = True
by simplegui.Frame._hide_controlpanel = True
https://simpleguics2pygame.readthedocs.io/en/latest/simpleguics2pygame/frame.html#SimpleGUICS2Pygame.simpleguics2pygame.frame.Frame._hide_controlpanel
See also _keep_timers option of SimpleGUICS2Pygame to help you:
https://simpleguics2pygame.readthedocs.io/en/latest/simpleguics2pygame/frame.html#SimpleGUICS2Pygame.simpleguics2pygame.frame.Frame._keep_timers
Possible improvements:
Find a better solution that don't use a global counter.
Stop timer when all work is finished.
I am trying to move only one sprite in a game loop including two sprites. I have included spr1 in the Bit.update() method so if w is pressed spr1.y -= 60. In other words the sprite is assigned to self in the hope that only spr1 will be moved when w is pressed. However, in the current code, pressing w moves both spr1 and spr2. How can I refer to and update only spr1 in the update method?
class Bit(games.Sprite):
def update(self):
if games.keyboard.is_pressed(games.K_w):
self = spr1
self.y -= 60
def main():
spr1_image = games.load_image("spr1.png")
spr1 = Bit(image = spr1_image,
x = games.screen.width / 10,
y = games.screen.height / 10)
spr2_image = games.load_image("spr2.png")
spr2 = Bit(image = spr2_image,
x = games.screen.width * 9 / 10,
y = games.screen.height * 9 / 10)
games.screen.add(spr1)
games.screen.add(spr2)
games.screen.mainloop()
main()
Edited
The two sprites have different behavior, so you need different classes for them.
In Bit, take out the self=spr1 line and you should be OK. In update(), self is whatever the current sprite is - spr1 or spr2.
In main, change spr2 to
spr2 = games.Sprite(image = spr2_image, # <---- changed class
x = games.screen.width * 9 / 10,
y = games.screen.height * 9 / 10)
Since spr2 doesn't need to respond to the keyboard, it doesn't need any behaviour that games.Sprite doesn't already provide. Therefore, you don't need to use Bit for it.
(Caveat: I haven't used livewires, so I may be missing something obvious :) )
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 8 years ago.
Improve this question
I have a class inside a file called Weapons.py called Pistol that looks like this:
class Pistol(object):
MAXAMMO = 6
def __init__(self, ammo):
if(ammo <= self.MAXAMMO):
self.ammo = ammo
def shoot(self):
if(ammo > 0):
accuracy = random.randint(0, 3)
return 3 * accuracy
ammo -= 1
else:
print("No ammo")
And a class called ColtM1911 that inherits from Pistol. It looks like this:
class ColtM1911(Pistol):
MAXAMMO = 7
def __init__(self, ammo):
self.ammo = 7
When I run:
import Player
import SetUp
from Utils import *
import pickle
import TitleAnimation
import os
import SaveLoad
from Weapons import *
gun = ColtM1911(5)
In another file it gives me "TypeError: object() takes no parameters" When trying this in the shell it worked, so I suspect it is to do with having it in a separate file.
The full traceback is,
Traceback (most recent call last):
File "C:\Users\James\Documents\game.py", line 3, in <module>
gun = Weapons.ColtM1911(5)
TypeError: object() takes no parameters
The only way I can recreate your error is if Pistol is actually defined as:
class Pistol(object()):
# ^ note extraneous parentheses
In Python 3.x, you don't need object at all; all classes are new-style by default. Also, there are logic errors and M1911.__init__ is redundant. Try something like:
import random
class Pistol:
MAXAMMO = 6
def __init__(self, ammo):
if ammo <= self.MAXAMMO:
self.ammo = ammo
else:
# what do you want do do here? Raise an error? Set ammo = MAXAMMO?
def shoot(self):
if self.ammo > 0:
self.ammo -= 1
return 3 * random.randint(0, 3)
else:
print("No ammo")
class ColtM1911(Pistol):
MAXAMMO = 7
Through using VPython, I am able to get the program I am working on to generate multiple balls by calling the same class. I am also able to have the balls appear within a selected random range when they are generated (across x, y and z).
However, I am currently stumped on how I get to call the pos / position function from within my loop - as I would like to have the balls move.
Please see my code so far below.
If I call Ball.pos it states as undefined, but if I place my positioning via self.position, only one ball is generated, as they are not being referred to from under the sphere details?
from visual import *
from random import *
scene.title = "Multi Balls"
wallBm = box(pos=(0,-6,0), size=(12.2,0.1,12.1), color=color.blue, opacity=0.4)
vscale = 0.1
deltat = 0.005
t = 0
scene.autoscale = False
i = 0
totalBalls = 10
class Ball:
def __init__(self):
self.velocity = vector(0,5,0)
#vel sample ([5,10,15,20,25],3)
sphere (pos=(randrange (-6,6),randrange (-6,6),randrange (-6,6)), radius=0.5, color=color.cyan)
while True:
rate(100)
if i < totalBalls:
Ball()
i = i + 1
t = 5 + deltat
Try Inheritance from frame:
class Ball(frame):
def __init__(self, pos=(randrange (-6,6),randrange (-6,6),randrange (-6,6))):
frame.__init__(self,pos=pos)
self.velocity = vector(0,5,0)
sphere(frame=self,pos=pos,radius=0.5, color=color.cyan)
listOfBalls=[]
while True:
rate(100)
for i in range(totalBalls):
listOfBalls.append(Ball())
now try again!
You can call each Ball's position by calling listOfBalls[3].pos. I hope this helps!
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