Hej,
python tells me that it cannot find the global name "SCREEN" is not defined.
Traceback (most recent call last):
File "C:\Python27\AntGame.py", line 443, in
run()
File "C:\Python27\AntGame.py", line 413, in run
ant.brain.set_state("exploring")
File "C:\Python27\AntGame.py", line 65, in set_state
self.active_state.entry_actions()
File "C:\Python27\AntGame.py", line 253, in random_destination
w, h = SCREEN.SIZE
here is my code. Cannot find the trick of this. I am a newbie ..
#its an "ant TV" simulation
SCREEN_SIZE = (640, 480)
NEST_POSITION = (320, 240)
ANT_COUNT = 20
NEST_SIZE = 100.
import pygame
from pygame.locals import *
from random import randint, choice
from GamOBjects.vector2 import Vector2
screen = pygame.display.set_mode(SCREEN_SIZE, 0, 32)
class State(object):
def __init__(self, name):
self.name = name
def do_actions(self):
pass
def check_conditions(self):
pass
def entry_actions(self):
pass
def exit_actions(self):
pass
class StateMachine(object):
def __init__(self):
self.states = {}
self.active_state = None
def add_state(self, state):
self.states[state.name] = state
def think(self):
if self.active_state is None:
return
self.active_state.do_actions()
new_state_name = self.active_state.check_conditions()
if new_state_name is not None:
self.set_state(new_state_name)
def set_state(self, new_state_name):
if self.active_state is not None:
self.active_state.exit_actions()
self.active_state = self.states[new_state_name]
self.active_state.entry_actions()
class World(object):
def __init__(self):
self.entities = {}
self.entit_id = 0
self.background = pygame.surface.Surface(SCREEN_SIZE).convert()
self.background.fill((255, 255, 255))
pygame.draw.circle(self.background, (200, 255, 200), NEST_POSITION, int(NEST_SIZE))
def add_entity(self, entity):
self.entities[self.entity_id] = entity
entity.id = self.entity_id
self.entity_id += 1
def remove_entity(self, entity):
del self.entities[entity.id]
def get(self, entity_id):
if entity_id in self.entities:
return self.entities[entity_id]
else:
return None
def process(self, time_passed):
time_passed_seconds = time_passed / 1000.0
for entity in self.entitites.itervalues():
entity.process(time_passed_seconds)
def render(self, surface):
surface.blit(self.background, (0, 0))
for entity in self.entities.values():
entity.render(surface)
def get_close_entity(self, name, location, range=100.):
location = Vector2(*location)
for entity in self.entities.values():
if entity.name == name:
distance = location.get_distance_to(entit_location)
if distance < range:
return entity
return None
class GameEntity(object):
def __init__(self, world, name, image):
self.world = world
self.name = name
self.image = image
self.location = Vector2(0, 0)
self.destination = Vector2(0, 0)
self.speed = 0.
self.brain = StateMachine()
self.id = 0
def render(self, surface):
x, y = self.location
w, h = self.image.get_size()
surface.blit(self.image, (x-w/2, y-h/2))
def process(self, time_passed):
self.brain.think()
if speed > 0 and self.location != self.destination:
vec_to_destination = self.destination - self.location
distance_to_destination = vec_to_destination.get_length()
heading = vec_to_destination.get_normalized()
travel_distance = min(distance_to_destination, time_passed * self.speed)
self.location += travel_distance * heading
class Leaf(GameEntity):
def __init__(self, world, image):
GameEntity.__init__(self, world, "spider", image)
class Spider(GameEntity):
def __init__(self, world, image):
self.dead_image = pygame.transform .flip(image, 0, 1)
self.health = 25
self.speed = 50. + randint(-20, 20)
def bitten(self):
self.health -= 1
if self.health <= 0:
self.speed=0.
self.image = self.dead_image
self.speed = 140.
def render(self, surface):
GameEntity.render(self, surface)
x, y = self.location
w, h = self.image.get_size()
bar_x = x - 12
bar_y = y + h/2
surface.fill( (255, 0, 0), (bar_x, bar_y, 25, 4))
surface.fill( (0, 255, 0), (bar_x, bar_y, self.health, 4))
def process(self, time_passed):
x, y = self.location
if x > SCREEN_SIZE[0] + 2:
self.world.remove_entity(self)
return
GameEntity.process(self, time_passed)
class Ant(GameEntity):
def __init__(self, world, image):
GameEntity.__init__(self, world, "ant", image)
exploring_state = AntStateExploring(self)
seeking_state = AntStateSeeking(self)
delivering_state = AntStateDelivering(self)
hunting_state = AntStateHunting(self)
self.brain.add_state(exploring_state)
self.brain.add_state(seeking_state)
self.brain.add_state(delivering_state)
self.brain.add_state(hunting_state)
self.carry_image = None
def carry(self, image):
self.carry_image = image
def drop(self, surface):
if self.carry_image:
x, y = self.location
w, h = self.carry_image.get_size()
surface.blit(self.carry_image, (x-w, y-h/2))
self.carry_image = None
def render(self, surface):
GameEntit.render(self, surface)
if self.carry_image:
x, y = self.location
w, h = self.carry_image.get_size()
surface.blit(self.carry_image, (x-w, y-h/2))
class AntStateExploring(State):
def __init__(self, ant):
State.__init__(self, "exploring")
self.ant = ant
def random_destination(self):
w, h = SCREEN.SIZE
self.ant.destination = vector2(randint(0, w), randint(0, h))
def do_actions(self):
if randint(1, 20) ==1:
self.random_destination()
def check_conditions(self):
leaf = self.ant.world.get_close_entity("leaf", self.ant.location)
if leaf is not None:
self.ant.leaf_id = leaf_id
return "seeking"
spider = self.ant.world.get_close_entity("spider", NEST_POSITION, NEST_SIZE)
if spider is not None:
if self.ant.location.get_distance_to(spider.location) < 100.:
self.ant.spider_id = spider.id
return "hunting"
return None
def entry_actions(self):
self.ant.speed = 120. + randint(-30, 30)
self.random_destination()
class AntStateSeeking(State):
def __init__(self, ant):
State.__init__(self, "Seeking")
self.ant = ant
self.leaf_id = None
def check_conditions(self):
leaf = self.ant.world.get(self.ant.leaf_id)
if leaf is None:
return "exploring"
if self.ant.location.get_distance_to(leaf.location) < 5.0:
self.ant.carry(image)
self.ant.world.remove_entity
return "delivering"
def entry_actions(self):
leaf = self.ant.world.get(self.ant.leaf_id)
if leaf is not None:
self.ant.destination = leaf.location
self.ant.speed = 160. + randint(-20, 20)
class AntStateDelivering(State):
def __init__(self, ant):
State.__init__(self, "delivering")
self.ant = ant
def check_conditions(self):
if Vector2(*NEST_POSITION).get_distance_to(self.ant.location) < NEST_SIZE:
if (randint(1, 10) == 1):
self.ant.drop(self.ant.world.background)
return "exploring"
return None
def entry_actions(self):
self.ant.speed = 60.
random_offset = Vector2(randint(-20, 20), randint(-20, 20))
self.ant.destination = Vector2(*NEST_POSITION) + random_offset
class AntStateHunting(State):
def __init__(self, ant):
State.__init__(self, "hunting")
self.ant = ant
self.got_kill = False
def do_actions(self):
spider = self.ant.world.get(self.ant.spider_id)
if spider is None:
return
self.ant.destination = spider.location
if self.ant.location.get_distance_to(spider.location) < 15.:
if randint(1, 5) == 1:
spider.bitten()
if spider.health <= 0:
self.ant.carry(spider.image)
self.ant.world.remove_entity(spider)
self.got_kill = True
def check_conditions(self):
if self.got_kill:
return "delivering"
spider = self.ant.world.get(self.ant.spider_id)
if spider is None:
return "exploring"
if spider.location.get_distance_to(NEST_POSITION) > NEST_SIZE * 3:
return exploring
return None
def entry_actions(self):
self.speed = 160. + randint(0, 50)
def exit_actions(self):
self.geot_kill = False
def run():
pygame.init()
world = World()
w, h = SCREEN_SIZE
clock = pygame.time.Clock()
ant_image = pygame.image.load("ant.png").convert_alpha()
leaf_image = pygame.image.load("leaf.png").convert_alpha()
spider_image = pygame.image.load("spider.png").convert_alpha()
for ant_no in xrange(ANT_COUNT):
ant = Ant(world, ant_image)
ant.location = Vector2(randint(0, w), randint(0, h))
ant.brain.set_state("exploring")
world.add_entity(ant)
while True:
for event in pygame.event.get():
if event.type == QUIT:
return
time_passed = clock.tick(30)
if randint(1, 10) == 1:
leaf = Leaf(world, leaf_image)
leaf.location = Vector2(randint(0, w), randint(0, h))
world.add_entity(leaf)
if randint(1, 100) == 1:
spider = Spider(world, spider_image)
spider.location = Vector2(-50, randint(0, h))
spider.destination = Vector2(w+50, randint(0,h))
world.add_entity(spider)
world.process(time_passed)
world.render(screen)
pygame.display.update()
if name == "main":
run()
You have a reference to SCREEN.SIZE, but the variable is clearly called SCREEN_SIZE.
The problem is that you tried to reference the variable SCREEN_SIZE, but typed SREEN.SIZE:
def random_destination(self):
w, h = SCREEN.SIZE
self.ant.destination = vector2(randint(0, w), randint(0, h))
Python assumes it has to look for an object named SCREEN and then return its attribute SIZE. SCREEN, however, does not exist. Change it to:
def random_destination(self):
w, h = SCREEN_SIZE
self.ant.destination = vector2(randint(0, w), randint(0, h))
This will unpack the contents of SCREEN_SIZE into w and h.
TBH, this is quite a trivial error message. Just curious ... how come you write such a big chunk of code and don't understand the traceback?
Related
I make a program where I generate circles of random size and position, by means of classes in python, I have managed to generate the circles as I wish but all collide with each other, so I have created a method so that this does not happen but it generates an error that I can not identify "'CreaCir' object has no attribute 'radio'", so I do not know what I'm doing wrong, the terminal tells me that the error is in the circle class in the collision method in the return, if someone could mark my error and give me advice to fix it I would appreciate it.
my code is as follows. first my circle class where I contain the collision method:
class Circulo(PosGeo):
def __init__(self, x, y, r):
self.x = x
self.y = y
self.radio = r
self.cx = x+r
self.cy = y+r
def dibujar(self, ventana):
pg.draw.circle(ventana, "white", (self.x, self.y), self.radio, 1)
def update(self):
pass
def colisionC(self, c2):
return self.radio + c2.radio > sqrt(pow(self.cx - c2.cx, 2) + pow(self.cy - c2.cy, 2))#where I get the error
now a part of my main code:
class CreaCir:
def __init__(self, figs):
self.i = 1
self.r = randint(5, 104)
self.x = randint(0, 500 + self.r)
self.y = randint(0, 300 + self.r)
self.creOne = Circulo(self.x, self.y, self.r)
self.figs.append(self.creOne)
def update(self):
if self.i <100:
choca = False
self.r = randint(5, 104)
self.x = randint(0, 500 + self.r)
self.y = randint(0, 300 + self.r)
self.creOne = Circulo(self.x, self.y, self.r)
for j in range (self.i):
choca = self.creOne.colisionC(self.figs[j])#here is where I use the collision method to my object
if choca == True:
break
if choca == False:
self.figs.append(self.creOne)
self.i+=1
def dibujar(self, ventana):
pass
called:
class Ventana:
def __init__(self, Ven_Tam= (700, 500)):
pg.init()
self.ven_tam = Ven_Tam
self.ven = pg.display.set_caption("Linea")
self.ven = pg.display.set_mode(self.ven_tam)
self.ven.fill(pg.Color('#404040'))
self.figs = []
self.figs.append(CreaCir(self.figs))
self.reloj = pg.time.Clock()
def check_events(self):
for event in pg.event.get():
if event.type == pg.QUIT or (event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE):
quit()
pg.display.flip()
def run(self):
while True:
self.check_events()
for fig in self.figs:
fig.update()
for fig in self.figs:
fig.dibujar(self.ven)
self.reloj.tick(30)
if __name__ == '__main__':
ven = Ventana()
ven.run()
The cause of the error is that you have put a CreaCir object in the figs list. So the first item in figs (self.creOne.colisionC(self.figs[j])) is a CreaCir object and this object has no radio.
Just remove that line of code, it is absolutely unnecessary.
self.figs.append(CreaCir(self.figs))
Create the CreaCir in run, but don't put it in the list:
class Ventana:
def __init__(self, Ven_Tam= (700, 500)):
pg.init()
self.ven_tam = Ven_Tam
self.ven = pg.display.set_caption("Linea")
self.ven = pg.display.set_mode(self.ven_tam)
self.ven.fill(pg.Color('#404040'))
self.figs = []
self.reloj = pg.time.Clock()
def check_events(self):
# [...]
def run(self):
cirCreater = CreaCir(self.figs)
while True:
self.check_events()
cirCreater.update()
for fig in self.figs:
fig.dibujar(self.ven)
self.reloj.tick(30)
To detect the collision of 2 circles, you need to calculate the distance between the centers of the circles and check if the distance is greater than the sum of the radii of the circles. The 3rd argument of pygame.draw.circle is the center of the circle, but not the top left of the bounding box of the circle:
pg.draw.circle(ventana, "white", (self.x, self.y), self.radio, 1)
pg.draw.circle(ventana, "white", (self.cx, self.cy), self.radio, 1)
Complete example:
import pygame as pg
import math, random
class Circulo:
def __init__(self, x, y, r):
self.x, self.y = x, y
self.radio = r
self.cx, self.cy = x+r, y+r
def dibujar(self, ventana):
pg.draw.circle(ventana, "white", (self.cx, self.cy), self.radio, 1)
def colisionC(self, c2):
dx = self.cx - c2.cx
dy = self.cy - c2.cy
return self.radio + c2.radio > math.sqrt(dx*dx + dy*dy)
class CreaCir:
def __init__(self, figs):
self.figs = figs
def update(self):
if len(self.figs) < 100:
choca = False
r = random.randint(5, 104)
x = random.randint(0, 700 - r*2)
y = random.randint(0, 500 - r*2)
creOne = Circulo(x, y, r)
for fig in self.figs:
choca = creOne.colisionC(fig)
if choca == True:
break
if choca == False:
self.figs.append(creOne)
class Ventana:
def __init__(self, Ven_Tam= (700, 500)):
pg.init()
self.ven_tam = Ven_Tam
self.ven = pg.display.set_caption("Linea")
self.ven = pg.display.set_mode(self.ven_tam)
self.figs = []
self.reloj = pg.time.Clock()
def check_events(self):
for event in pg.event.get():
if event.type == pg.QUIT or (event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE):
quit()
def run(self):
cirCreater = CreaCir(self.figs)
while True:
self.check_events()
cirCreater.update()
self.ven.fill(pg.Color('#404040'))
for fig in self.figs:
fig.dibujar(self.ven)
pg.display.flip()
self.reloj.tick(30)
if __name__ == '__main__':
ven = Ventana()
ven.run()
I am trying to create a "Basketball game" using python and tkinter and I'm having trouble making my animation work. When I press the spacebar the basketball appears but it doesnt go upwards. I tried placing self.status.shoot == Status.shoot in multiple areas but the animation doesn't start once I hit the spacebar, instead the image of the basketball simply appears without movement. Any thoughts?
Here is my code:
model.py
import enum,math,random,time
# sizes of each images (pixels)
from Projects.MVC import controller
backboard1_height = 150
backboard1_width = 150
backboard2_height = 150
backboard2_width = 150
backboard3_height = 150
backboard3_width = 150
bg_height = 750
bg_width = 1000
floor_height = 180
floor_width = 1000
player_height = 250
player_width = 250
ball_height = 50
ball_width = 50
class Status(enum.Enum):
run = 1
pause = 2
game_over = 3
terminate = 4
shoot = 5
class HorizontalDirection(enum.IntEnum):
left = -1
none = 0
right = 1
class VerticalDirection(enum.IntEnum):
up = -1
none = 0
down = 1
class ImgDirection(enum.Enum):
left = -1
right = 1
class GameModel:
def __init__(self):
self.status = Status.pause
self.elements = []
self.next_time = time.time() # when we try drop a ball
# create elements
self.bg = Background(bg_width / 2, bg_height / 2)
self.floor = Floor(bg_width / 2, bg_height - (floor_height / 2))
self.backboard1 = Backboard1(bg_width / 2, player_height / 2)
self.backboard2 = Backboard2(bg_width / 10, player_height / 2)
self.backboard3 = Backboard3((bg_width / 2) + 400, player_height / 2)
self.player = Player(bg_width / 2, bg_height - floor_height )
self.text = TextInfo(80, 30)
self.init_elements()
def init_elements(self): # layer images on top of each other in order for every thing to be seen
self.elements = []
self.elements.append(self.bg)
self.elements.append(self.floor)
self.elements.append(self.backboard1)
self.elements.append(self.backboard2)
self.elements.append(self.backboard3)
self.elements.append(self.player)
self.elements.append(self.text)
def add_ball(self):
ball = Ball(self.player.x, self.player.y-125)
print("first self.player.y: {}".format(self.player.y))
#if self.status == Status.shoot:
self.elements.append(ball)
def random_ball_drop(self):
# if self.status == Status.shoot:
if self.next_time - time.time() < -2:
# if self.status == Status.shoot:
self.next_time = time.time() + 2
self.add_ball()
print("First time: {}".format(time.time()))
print("first Add.ball: {}".format(self.add_ball()))
#if self.status == Status.shoot:
elif self.next_time - time.time() < 0:
if random.uniform(0, 1) < 0.01:
self.next_time = time.time() + 2
self.add_ball()
print("Second time: {}".format(time.time()))
def check_status(self, element):
if type(element) is Ball:
dist = math.sqrt((element.x - self.backboard1.x) ** 2 + (element.y - self.backboard1.y) ** 2)
if dist < self.backboard1.catch_radius:
self.text.score += 1
return False
elif element.y >= bg_height:
self.text.lives -= 1
print("Text.lives: {}".format(self.text.lives))
return False
return True
def remove_ball(self):
self.elements = [e for e in self.elements if self.check_status(e)]
#print("self.element: {}".format(self.elements))
def update(self):
# if self.status == Status.shoot:
for element in self.elements:
element.update()
#print("first element.update: {}".format(element.update()))
# if self.status == Status.shoot:
self.random_ball_drop()
self.remove_ball()
print("Random_ball_drop from update block: {}".format(self.random_ball_drop()))
print("remove_ball: {}".format(self.remove_ball()))
def change_to_initial_state(self):
self.init_elements()
for e in self.elements:
e.change_to_initial_position()
class GameElement:
def __init__(self, x, y, direction_x, direction_y, speed):
self.initial_x = x
self.initial_y = y
self.x = x
self.y = y
self.direction_x = direction_x
self.direction_y = direction_y
self.speed = speed
def change_to_initial_position(self):
self.x = self.initial_x
self.y = self.initial_y
def update(self):
pass
class Background(GameElement):
def __init__(self, x, y):
super().__init__(x, y, HorizontalDirection.none, VerticalDirection.none, 0)
class Floor(GameElement):
def __init__(self, x, y):
super().__init__(x, y, HorizontalDirection.none, VerticalDirection.none, 0)
class Backboard1(GameElement):
def __init__(self, x, y):
super().__init__(x, y, HorizontalDirection.none, VerticalDirection.none, 0)
self.catch_radius = (backboard1_height / 2) + (ball_height / 2) + 10
class Backboard2(GameElement):
def __init__(self, x, y):
super().__init__(x, y, HorizontalDirection.none, VerticalDirection.none, 0)
self.catch_radius = (backboard2_height / 2) + (ball_height / 2) + 10
class Backboard3(GameElement):
def __init__(self, x, y):
super().__init__(x, y, HorizontalDirection.none, VerticalDirection.none, 0)
self.catch_radius = (backboard3_height / 2) + (ball_height / 2) + 10
class Player(GameElement):
def __init__(self, x, y):
super().__init__(x, y, HorizontalDirection.none, VerticalDirection.none, speed=6)
self.img_direction = ImgDirection.left
def update(self):
if self.direction_x == HorizontalDirection.left:
if self.x > 0:
self.move()
elif self.direction_x == HorizontalDirection.right:
if self.x < bg_width:
self.move()
def move(self):
self.x += self.direction_x * self.speed
self.direction_x = HorizontalDirection.none
class Ball(GameElement):
def __init__(self, x, y):
super().__init__(x, y, HorizontalDirection.none, VerticalDirection.up, speed=10)
def update(self):
self.y += self.direction_y*self.speed
print("This is self.y: {}".format(self.y))
class TextInfo(GameElement):
def __init__(self, x, y):
super().__init__(x, y, HorizontalDirection.none, VerticalDirection.none, speed=0)
self.score = 0
self.lives = 3
def change_to_initial_position(self):
self.score = 0
self.lives = 3
super().change_to_initial_position()
controller.py
from model import *
class GameController:
def __init__(self, model):
self.model = model
pass
def start_new_game(self):
self.model.change_to_initial_state()
self.model.status = Status.run
def continue_game(self):
self.model.status = Status.run
print(Status.run)
def exit_game(self):
self.model.status = Status.terminate
def press_p(self, event):
if self.model.status == Status.run:
self.model.status = Status.pause
print(Status.pause)
def press_left(self, event):
self.model.player.direction_x = HorizontalDirection.left
self.model.player.img_direction = ImgDirection.left
print(HorizontalDirection.left)
def press_right(self, event):
self.model.player.direction_x = HorizontalDirection.right
self.model.player.img_direction = ImgDirection.right
print(HorizontalDirection.right)
def press_space(self, event):
if self.model.status == Status.run:
self.model.status = Status.shoot
self.model.update()
print(Status.shoot)
def update_model(self):
if self.model.status == Status.run:
self.model.update()
view.py
import tkinter as tk
from PIL import ImageTk, Image
from model import *
class GameImages:
def __init__(self):
# background
self.bg_pil_img = Image.open('./resources/bg.png')
self.bg_img = ImageTk.PhotoImage(self.bg_pil_img)
# floor
self.floor_pil_img = Image.open('./resources/floor.png')
self.floor_img = ImageTk.PhotoImage(self.floor_pil_img)
# backboard1
self.backboard1_pil_img = Image.open('./resources/backboard1.png')
self.backboard1_pil_img = self.backboard1_pil_img.resize((backboard1_height, backboard1_width))
self.backboard1_img = ImageTk.PhotoImage(self.backboard1_pil_img)
# backboard2
self.backboard2_pil_img = Image.open('./resources/backboard2.png')
self.backboard2_pil_img = self.backboard2_pil_img.resize((backboard2_height, backboard2_width))
self.backboard2_img = ImageTk.PhotoImage(self.backboard2_pil_img)
# backboard3
self.backboard3_pil_img = Image.open('./resources/backboard3.png')
self.backboard3_pil_img = self.backboard1_pil_img.resize((backboard3_height, backboard3_width))
self.backboard3_img = ImageTk.PhotoImage(self.backboard3_pil_img)
# player
self.player_pil_img = Image.open('./resources/player.png')
self.player_pil_img_right = self.player_pil_img.resize((player_height, player_width))
self.player_pil_img_left = self.player_pil_img_right.transpose(Image.FLIP_LEFT_RIGHT)
self.player_img_right = ImageTk.PhotoImage(self.player_pil_img_right)
self.player_img_left = ImageTk.PhotoImage(self.player_pil_img_left)
# ball
self.ball_pil_img = Image.open('./resources/ball.png')
self.ball_pil_img = self.ball_pil_img.resize((ball_height, ball_width))
self.ball_img = ImageTk.PhotoImage(self.ball_pil_img)
def get_image(self, element):
if type(element) is Background:
return self.bg_img
if type(element) is Floor:
return self.floor_img
if type(element) is Backboard1:
return self.backboard1_img
if type(element) is Backboard2:
return self.backboard2_img
if type(element) is Backboard3:
return self.backboard3_img
if type(element) is Player:
if element.img_direction == ImgDirection.left:
return self.player_img_left
else:
return self.player_img_right
if type(element) is Ball:
return self.ball_img
return None
class DisplayGame:
def __init__(self, canvas, _id):
self.canvas = canvas
self.id = _id
def delete_from_screen(self):
self.canvas.delete(self.id)
class DisplayGameImage(DisplayGame):
def __init__(self, canvas, element, img):
super().__init__(canvas, canvas.create_image(element.x, element.y, image=img))
class DisplayGameText(DisplayGame):
def __init__(self, canvas, element):
text = "Score: %d\nLives: %d" % (element.score, element.lives)
super().__init__(canvas, canvas.create_text(element.x, element.y, font='12', text=text))
class DisplayMenu(DisplayGame):
def __init__(self, root, canvas, controller):
menu = tk.Frame(root, bg='grey', width=400, height=40)
menu.pack(fill='x')
new_game = tk.Button(menu, text="New Game", width=15, height=2, font='12', command=controller.start_new_game)
new_game.pack(side="top")
continue_game = tk.Button(menu, text="Continue", width=15, height=2, font='12', command=controller.continue_game)
continue_game.pack(side="top")
exit_game = tk.Button(menu, text="Exit Game", width=15, height=2, font='12', command=controller.exit_game)
exit_game.pack(side="top")
_id = canvas.create_window(bg_width / 2, bg_height / 2, window=menu)
super().__init__(canvas, _id)
class GameView:
def __init__(self, model, controller):
self.model = model
self.controller = controller
# root
self.root = tk.Tk()
self.root.title('Basketball Game')
# load images files
self.images = GameImages()
# canvas
self.canvas = tk.Canvas(self.root, width= bg_width, height= bg_height)
self.canvas.pack()
self.root.update()
# canvas elements id
self.elements_id = []
self.add_elements_to_canvas()
self.add_event_handlers()
self.is_menu_open = False
self.draw()
self.root.mainloop()
def add_elements_to_canvas(self):
for e in self.model.elements:
if type(e) is TextInfo:
self.elements_id.append(DisplayGameText(self.canvas, e))
else:
self.elements_id.append(DisplayGameImage(self.canvas, e, self.images.get_image(e)))
if self.model.status == Status.pause or self.model.status == Status.game_over:
self.elements_id.append(DisplayMenu(self.root, self.canvas, self.controller))
self.is_menu_open = True
def add_event_handlers(self):
self.root.bind("<Left>", self.controller.press_left)
self.root.bind("<Right>", self.controller.press_right)
self.root.bind("p", self.controller.press_p)
self.root.bind("<space>",self.controller.press_space)
def draw(self):
self.controller.update_model()
if self.model.status == Status.run or not self.is_menu_open:
self.is_menu_open = False
self.canvas.delete("all")
self.add_elements_to_canvas()
if self.model.status == Status.terminate:
self.root.destroy()
else:
self.canvas.after(5, self.draw)
This question already has answers here:
Create trails of particles for the bullets
(1 answer)
Pygame change particle color
(1 answer)
Closed 5 months ago.
I am a beginner with pygame. I want to include a few "Emitter" classes to "Particle" class to show points. It doesn't work and I don't know how to fix it. I think the problem is with gfxdraw. In the "Emitter" class, it initializes the system window. This can also be a problem. I don't know how to transfer this to the "Particle" class. Would it help at all? I used many combinations for repair. Nothing works. Please help. Does anyone have any idea?
import random
import sys
import pygame
from pygame.locals import *
import pygame.gfxdraw
class ParticleSystem:
def __init__(self, id, pos, a,b, width, height, radius, color):
self.id = id
self.width = width
self.height = height
self.radius = radius
self.color = color
self.g = 9.81
self.pos = [random.randint(a,b), 0]
self.enabled = True
self.df = 0
def update(self, time, collision):
if self.enabled:
v = 1 / float(time)
if not self.collision_detect(collision):
self.pos[1] += self.g*v
else:
self.enabled = False
if self.df != 0:
F = (self.g*v)/9
if self.df < 0:
F = -F
self.pos[0] += F
self.df -= F
def collision_detect(self, collision):
x = int(self.pos[0])
y = self.pos[1]
r = self.radius
points = collision[x-r:x+r]
for p in points:
if y + r >= p:
for i in range(x-r, x+r):
if i >= 0 and i < self.width:
collision[i] = y
return True
if self.pos[1] >= self.height:
return True
else:
return False
def draw(self, surface):
pygame.gfxdraw.filled_circle(surface, int(self.pos[0]), int(self.pos[1]), self.radius, self.color)
pygame.gfxdraw.aacircle(surface, int(self.pos[0]), int(self.pos[1]), self.radius, self.color)
class Emitter:
def __init__(self, a, b, height, width):
self.a = a
self.b = b
self.timer = 60
self.width = width
self.height = height
self.color = (255, 255, 255)
self.background_color = (0, 0, 0)
self.pos = [0,0]
self.particles = []
self.counter = 0
self.freq = 5
self.size = 4
self.collision = [height] * width
self.df_c = 1
self.df_f = 100
self.begin()
def begin(self):
self.screen = pygame.display.set_mode((self.width, self.height))
self.clock = pygame.time.Clock()
while 1:
time = self.clock.get_time()
self.update(time)
self.clock.tick(self.timer)
self.render(time)
def update(self, time):
if self.counter > self.freq:
self.counter = 0
particle = ParticleSystem(len(self.particles), self.pos, self.a, self.b, self.width, self.height, self.size, self.color)
self.particles.append(particle)
else:
self.counter += 1
df_c = random.randint(0, 100)
df_f = 0
if df_c <= self.df_c:
df_f = random.randint(-self.df_f, self.df_f)
for part in self.particles:
if part.enabled:
if df_f != 0:
part.df = df_f
part.update(time, self.collision)
def render(self, time):
surface = pygame.Surface(self.screen.get_size())
surface.convert()
surface.fill(self.background_color)
for part in self.particles:
part.draw(surface)
self.screen.blit(surface, (0, 0))
pygame.display.flip()
class Particle:
def __init__(self, width, height, caption):
self.width = width
self.height = height
self.caption = caption
self.initialization()
def initialization(self):
pygame.init()
pygame.display.set_caption(self.caption)
#Emitter(0, self.width, self.height, self.width)
Emitter(0, 125, self.height, self.width)
Emitter(200, 500, self.height, self.width) #how to show the second Emitter
self.input(pygame.event.get())
def input(self, events):
for event in events:
if event.type == pygame.QUIT:
sys.exit(0)
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
sys.exit(0)
if __name__ == "__main__":
particle = Particle(800, 600, "Particle System - Christmas Time")
I am pretty new at coding, and am wondering how I would animate my sprite to look like it is actually moving. I think I have a general idea, but honestly I do not know where to start in my code to insert the different images and make it look like it's moving. This is my code, any tips are greatly appreciated.
SCREEN_SIZE = (1024, 768)
import sys
import pygame
from pygame.locals import *
from random import randint, choice
from Vector2 import Vector2
NEST_POSITION = (SCREEN_SIZE[0]/2, SCREEN_SIZE[1]/2)
NEST_POSITION_VECTOR2 = Vector2(NEST_POSITION)
ANT_COUNT = 20
NEST_SIZE = 100.
class State(object):
def __init__(self, name):
self.name = name
def do_actions(self):
pass
def check_conditions(self):
pass
def entry_actions(self):
pass
def exit_actions(self):
pass
class StateMachine(object):
def __init__(self):
self.states = {}
self.active_state = None
def add_state(self, state):
self.states[state.name] = state
def think(self):
if self.active_state is None: return
self.active_state.do_actions()
new_state_name = self.active_state.check_conditions()
if new_state_name is not None:
self.set_state(new_state_name)
def set_state(self, new_state_name):
if self.active_state is not None:
self.active_state.exit_actions()
self.active_state = self.states[new_state_name]
self.active_state.entry_actions()
class World(object):
def __init__(self):
self.entities = {}
self.entity_id = 0
self.background = pygame.surface.Surface(SCREEN_SIZE).convert()
self.background.fill((255, 255, 255))
pygame.draw.circle(self.background, (200, 255, 200), NEST_POSITION, int(NEST_SIZE))
def add_entity(self, entity):
self.entities[self.entity_id] = entity
entity.id = self.entity_id
self.entity_id += 1
def remove_entity(self, entity):
del self.entities[entity.id]
def get(self, entity_id):
if entity_id in self.entities:
return self.entities[entity_id]
else:
return None
def process(self, time_passed):
time_passed_seconds = time_passed / 1000.0
for entity in self.entities.values():
entity.process(time_passed_seconds)
def render(self, surface):
surface.blit(self.background, (0, 0))
for entity in self.entities.itervalues():
entity.render(surface)
def get_close_entity(self, name, location, range=100.):
for entity in self.entities.itervalues():
if (entity.name == name):
distance = location.get_distance_to(entity.location)
if (distance < range):
return entity
return None
############################# GameEntity ####################################
## This is a "template" object - that is, we never actually create one of
## these objects in the game.
## This object is used as a base templet for other game objects that "extend"
## or "inherit from" this object.
## The leaf, Spider and And objects all extend the GameEntity object
class GameEntity(object):
def __init__(self, world, name, image):
self.world = world
self.name = name
self.image = image
self.location = Vector2(0, 0)
self.destination = Vector2(0, 0)
self.speed = 0.
self.brain = StateMachine()
self.id = 0
def render(self, surface):
w, h = self.image.get_size()
surface.blit(self.image, (self.location.x-w/2, self.location.y-h/2))
def process(self, time_passed):
self.brain.think()
if ((self.speed > 0.) and (self.location != self.destination)):
vec_to_destination = self.destination - self.location
distance_to_destination = vec_to_destination.get_magnitude()
heading = vec_to_destination.get_normalized()
travel_distance = min(distance_to_destination, time_passed * self.speed)
self.location += heading * travel_distance
############################# Leaf ##########################################
class Leaf(GameEntity):
def __init__(self, world, image):
GameEntity.__init__(self, world, "leaf", image)
############################# Ant ##########################################
class Spider(GameEntity):
def __init__(self, world, image):
GameEntity.__init__(self, world, "spider", image)
self.dead_image = pygame.transform.flip(image, 0, 1)
self.health = 25
self.speed = 50. + randint(-20, 20)
def bitten(self):
self.health -= 1
if (self.health <= 0):
self.speed = 0.
self.image = self.dead_image
self.speed = 140.
def render(self, surface):
GameEntity.render(self, surface)
w, h = self.image.get_size()
bar_x = self.location.x - 12
bar_y = self.location.y + h/2
surface.fill( (255, 0, 0), (bar_x, bar_y, 25, 4))
surface.fill( (0, 255, 0), (bar_x, bar_y, self.health, 4))
def process(self, time_passed):
if (self.location.x > SCREEN_SIZE[0] + 2):
self.world.remove_entity(self)
return
GameEntity.process(self, time_passed)
############################# Ant ##########################################
class Ant(GameEntity):
def __init__(self, world, image):
GameEntity.__init__(self, world, "ant", image)
exploring_state = AntStateExploring(self)
seeking_state = AntStateSeeking(self)
delivering_state = AntStateDelivering(self)
hunting_state = AntStateHunting(self)
self.brain.add_state(exploring_state)
self.brain.add_state(seeking_state)
self.brain.add_state(delivering_state)
self.brain.add_state(hunting_state)
self.carry_image = None
def carry(self, image):
self.carry_image = image
def drop(self, surface):
if self.carry_image:
x = self.location.x
y = self.location.y
w, h = self.carry_image.get_size()
surface.blit(self.carry_image, (x-w, y-h/2))
self.carry_image = None
def render(self, surface):
GameEntity.render(self, surface)
if (self.carry_image):
x = self.location.x
y = self.location.y
w, h = self.carry_image.get_size()
surface.blit(self.carry_image, (x-w, y-h/2))
############################# AntStateExploring #############################
class AntStateExploring(State):
def __init__(self, ant):
State.__init__(self, "exploring")
self.ant = ant
def random_destination(self):
w, h = SCREEN_SIZE
self.ant.destination = Vector2(randint(0, w), randint(0, h))
def do_actions(self):
if (randint(1, 20) == 1):
self.random_destination()
def check_conditions(self):
leaf = self.ant.world.get_close_entity("leaf", self.ant.location)
if (leaf is not None):
self.ant.leaf_id = leaf.id
return "seeking"
spider = self.ant.world.get_close_entity("spider", NEST_POSITION_VECTOR2, NEST_SIZE)
if (spider is not None):
if (self.ant.location.get_distance_to(spider.location) < 100.):
self.ant.spider_id = spider.id
return "hunting"
return None
def entry_actions(self):
self.ant.speed = 120. + randint(-30, 30)
self.random_destination()
############################# AntStateSeeking ###############################
class AntStateSeeking(State):
def __init__(self, ant):
State.__init__(self, "seeking")
self.ant = ant
self.leaf_id = None
def check_conditions(self):
leaf = self.ant.world.get(self.ant.leaf_id)
if (leaf is None): return "exploring"
if (self.ant.location.get_distance_to(leaf.location) < 5.0):
self.ant.carry(leaf.image)
self.ant.world.remove_entity(leaf)
return "delivering"
return None
def entry_actions(self):
leaf = self.ant.world.get(self.ant.leaf_id)
if (leaf is not None):
self.ant.destination = leaf.location
self.ant.speed = 160. + randint(-20, 20)
############################# AntStateDelivering ############################
class AntStateDelivering(State):
def __init__(self, ant):
State.__init__(self, "delivering")
self.ant = ant
def check_conditions(self):
if (self.ant.location.get_distance_to(NEST_POSITION) < NEST_SIZE):
if (randint(1, 10) == 1):
self.ant.drop(self.ant.world.background)
return "exploring"
return None
def entry_actions(self):
self.ant.speed = 60.
random_offset = Vector2(randint(-20, 20), randint(-20, 20))
self.ant.destination = random_offset + NEST_POSITION
############################# AntStateHunting ###############################
class AntStateHunting(State):
def __init__(self, ant):
State.__init__(self, "hunting")
self.ant = ant
self.got_kill = False
def do_actions(self):
spider = self.ant.world.get(self.ant.spider_id)
if (spider is None): return
self.ant.destination = spider.location
if (self.ant.location.get_distance_to(spider.location) < 15.):
if (randint(1, 5) == 1):
spider.bitten()
if (spider.health <= 0):
self.ant.carry(spider.image)
self.ant.world.remove_entity(spider)
self.got_kill = True
def check_conditions(self):
if (self.got_kill): return "delivering"
spider = self.ant.world.get(self.ant.spider_id)
if (spider is None): return "exploring"
if (spider.location.get_distance_to(NEST_POSITION) > NEST_SIZE * 3):
return "exploring"
return None
def entry_actions(self):
self.speed = 160. + randint(0, 50)
def exit_actions(self):
self.got_kill = False
############################# Set up Game ###############################
def run():
pygame.init()
screen = pygame.display.set_mode(SCREEN_SIZE, 0, 32)
pygame.display.set_caption("The Super Amazing Ant Simulation")
world = World()
w, h = SCREEN_SIZE
clock = pygame.time.Clock()
ant_image = pygame.image.load("ant.png").convert_alpha()
ant2_image = pygame.image.load("ant6.gif").convert_alpha()
ant3_image = pygame.image.load("ant7.gif").convert_alpha()
leaf_image = pygame.image.load("leaf.png").convert_alpha()
spider_image = pygame.image.load("spider.png").convert_alpha()
############# Place ants in starting locations #########################
for ant_no in xrange(ANT_COUNT):
ant = Ant(world, ant_image)
ant.location = Vector2(randint(0, w), randint(0, h))
ant.brain.set_state("exploring")
world.add_entity(ant)
############################# Game Loop ###############################
while (True):
for event in pygame.event.get():
if (event.type == QUIT):
pygame.quit()
return
time_passed = clock.tick(30)
if (randint(1, 50) == 1):
leafX = randint(0, w)
leafY = randint(0, h)
numberOfLeafs = randint(5,25)
for leafNumber in range(numberOfLeafs):
leaf = Leaf(world, leaf_image)
leaf.location = Vector2(leafX, leafY)
world.add_entity(leaf)
if (randint(1, 100) == 1):
spider = Spider(world, spider_image)
spider.location = Vector2(-50, randint(0, h))
spider.destination = Vector2(w+50, randint(0, h))
world.add_entity(spider)
world.process(time_passed)
world.render(screen)
pygame.display.update()
############################# Call run to start game #########################
try:
if (Vector2.version() != "Version 2014-04-09"):
raise()
except:
print "****ERROR**** Vector2 version mis-matched with AntSimulation.py"
sys.exit()
run()
In pygame, an animation is just multiple images played in a sequence. I'm assuming that because you are wanting to animate a sprite you already have an image sequence in mind to use.
Here is a basic example of an animation class (you will probably want to add quite a bit of functionality to this):
class Animation(object):
def __init__(self, image_list):
self.image_list = image_list #a list of pygame images
self.total_frames = len(image_list)
self.index = 0
def next(self):
image = self.image_list[self.index]
self.index = (self.index+1) % self.total_frames #loops back around
return image
Now, in your sprite class, when you are ready to switch to the next frame of your animation:
self.image = my_animation.next()
How do you make this code work: Just have pyglet installed and change assassin1.png,assassin2.png and assassin3.png with the name of images stored in the directory where you saved this code to a file.
import pyglet
def sprite_type(type_ = "standing"):
if type_ == "moving-forward":
moving_forward_image_list = [pyglet.image.load('assassin2.png'), pyglet.image.load('assassin3.png')]
moving_forward_animation = pyglet.image.Animation.from_image_sequence(moving_forward_image_list, 0.3)
return moving_forward_animation
if type_ == "standing":
standing_animation = pyglet.image.load("assassin1.png")
return standing_animation
class Assassin(pyglet.sprite.Sprite):
def __init__(self, batch, img):
pyglet.sprite.Sprite.__init__(self, img, x = 50, y = 30)
class Game(pyglet.window.Window):
def __init__(self):
pyglet.window.Window.__init__(self, width = 315, height = 220)
self.batch_draw = pyglet.graphics.Batch()
self.player_dict = {"standing": Assassin(batch = self.batch_draw, img = sprite_type()), "moving-forward": Assassin(batch = self.batch_draw, img = sprite_type(type_ = "moving-forward"))}
self.player = self.player_dict["standing"]
self.fps_display = pyglet.clock.ClockDisplay()
self.keys_held = []
self.schedule = pyglet.clock.schedule_interval(func = self.update, interval = 1/60.)
def on_draw(self):
self.clear()
self.fps_display.draw()
self.batch_draw.draw()
self.player.draw()
def on_key_press(self, symbol, modifiers):
self.keys_held.append(symbol)
if symbol == pyglet.window.key.RIGHT:
self.player = self.player_dict["moving-forward"]
print "The 'RIGHT' key was pressed"
def on_key_release(self, symbol, modifiers):
self.keys_held.pop(self.keys_held.index(symbol))
self.player = self.player_dict["standing"]
def update(self, interval):
if pyglet.window.key.RIGHT in self.keys_held:
self.player.x += 50 * interval
if __name__ == "__main__":
window = Game()
pyglet.app.run()
This code displays assassin1.png while no key is held at position (50 30), when the right key is held the character moves forward and every 0.3 seconds the 2 images assassin2.png and assassin3.png are switched as to give the illusion of a walking character. Also the fps are shown.
Currently when you release the key the character will return to the original position (50, 30). When you press the key again the character moves from the position where the walking character stopped last.
I understand why this happens because the walking animation character and the standing character are two different instances of the same class.
I first thought using class variables I would be able to store the position. But I can't seem to come up with a working solution. Does anyone have any ideas what I could do?
Edit 1 (#Hugh Bothwell)
import pyglet
def sprite_type(type_ = "standing"):
if type_ == "moving-forward":
moving_forward_image_list = [pyglet.image.load('assassin2.png'), pyglet.image.load('assassin3.png')]
moving_forward_animation = pyglet.image.Animation.from_image_sequence(moving_forward_image_list, 0.3)
return moving_forward_animation
if type_ == "standing":
standing_animation = pyglet.image.load("assassin1.png")
return standing_animation
class Assassin(pyglet.sprite.Sprite):
def __init__(self, batch, img):
pyglet.sprite.Sprite.__init__(self, img, x = 50, y = 30)
def stand(self, batch, img):
self.batch = batch
self.img = img
def move(self, batch, img):
self.batch = batch
self.img = img
class Game(pyglet.window.Window):
def __init__(self):
pyglet.window.Window.__init__(self, width = 315, height = 220)
self.batch_draw = pyglet.graphics.Batch()
self.player = Assassin(batch = self.batch_draw, img = sprite_type())
self.fps_display = pyglet.clock.ClockDisplay()
self.keys_held = []
self.schedule = pyglet.clock.schedule_interval(func = self.update, interval = 1/60.)
def on_draw(self):
self.clear()
self.fps_display.draw()
self.batch_draw.draw()
self.player.draw()
def on_key_press(self, symbol, modifiers):
self.keys_held.append(symbol)
if symbol == pyglet.window.key.RIGHT:
self.player.move(batch = self.batch_draw, img = sprite_type("moving-forward"))
# if I put the following line here instead:
#self.player = self.player.move(batch = self.batch_draw, img = sprite_type("moving-forward"))
# I get this error when pressing the <right-direction> key:
#self.player.draw(), AttributeError: 'NoneType' object has no attribute 'draw'
print "The 'RIGHT' key was pressed"
def on_key_release(self, symbol, modifiers):
self.keys_held.pop(self.keys_held.index(symbol))
self.player.stand(batch = self.batch_draw, img = sprite_type("standing"))
def update(self, interval):
if pyglet.window.key.RIGHT in self.keys_held:
self.player.x += 50 * interval
if __name__ == "__main__":
window = Game()
pyglet.app.run()
Instead of having a standing-character and a walking-character, you need one character who has a movement-state.