What I want is two things:
count the number of enemies on the screen. And remove all enemies from the screen with a contion.
The second chose is to allow enemies to shoot randomly
class Enemy(Particle):
active = False
tex_name = 'ufo'
v = 0
def reset(self, created=False):
self.active = False
self.x = -100
self.y = -100
self.v = 0
def advance(self, nap):
if self.active:
if self.check_hit():
self.reset()
return
self.x -= 200 * nap
if self.x < -50:
self.reset()
return
self.y += self.v * nap
if self.y <= 0:
self.v = abs(self.v)
elif self.y >= self.parent.height:
self.v = -abs(self.v)
elif self.parent.spawn_delay <= 0:
self.active = True
self.x = self.parent.width + 50
self.y = self.parent.height * random()
self.v = randint(-100, 100)
self.parent.spawn_delay += 1
def check_hit(self):
if math.hypot(self.parent.player_x - self.x,
self.parent.player_y - self.y) < 60:
return True
for b in self.parent.bullets:
if not b.active:
continue
if math.hypot(b.x - self.x, b.y - self.y) < 30:
b.reset()
return True
What I want is two things:
count the number of enemies on the screen. And remove all enemies from the screen with a contion.
The second chose is to allow enemies to shoot randomly
You can accomplish the first two of your questions by modifying the PSWidget class. By adding two attributes enemy_count and killall to the class:
class PSWidget(Widget):
indices = []
vertices = []
particles = []
enemy_count = 0
killall = False
And using those attributes in the update_glsl() method:
def update_glsl(self, nap):
self.enemy_count = 0 # initialize enemy count
for p in self.particles:
if isinstance(p, Enemy) and p.active:
if self.killall:
p.reset() # kill this enemy
else:
self.enemy_count += 1 # increment enemy count
p.advance(nap)
p.update()
self.canvas.clear()
with self.canvas:
Mesh(fmt=self.vfmt, mode='triangles',
indices=self.indices, vertices=self.vertices,
texture=self.texture)
# reset killall
self.killall = False
So, anytime you want the count of active enemies, just use the enemy_count attribute of the PSWidget instance. And whenever you want to kill all the active enemies, just set the killall attribute of the PSWidget instance.
As far as your third question, show us your attempt at coding that.
If you are using an answer that I gave in another question, where I suggested using the on_enter() method to start the game updates, then you can use on_leave() to stop the updates. The game movements are faster every time you enter MainScreen because more updates are scheduled on each entry. Here is a modified MainScreen that handles that handles that issue:
class MainScreen(Screen):
started = BooleanProperty(False)
def on_enter(self, *args):
if not self.started:
self.ids.game.initialize()
self.started = True
self.update_event = Clock.schedule_interval(self.ids.game.update_glsl, 1.0/60.0)
def on_leave(self, *args):
if self.update_event is not None:
self.update_event.cancel()
Related
cant move the character at the same time the obstacle is moving, pirincipal is the name of the image that works as the player
def move():
def left(event):
x = -5
y = 0
canvasGame.update()
edgeReached()
canvasGame.move(principal,x, y)
collision()
def right(event):
x = 5
y = 0
canvasGame.update()
edgeReached()
canvasGame.move(principal,x, y)
collision()
canvasGame.bind_all("<Left>", left)
canvasGame.bind_all("<Right>", right
move()
class Barrel:
def __init__(self, canvas):
self.canvas = canvas
self.obs = canvasGame.create_image(125, 500, image=nuevoObs, anchor=tk.NW)
self.x = 16
self.y = 0
def movement(self):
while True:
coords = canvasGame.coords(self.obs)
if (coords[0] >= 1000):
self.x = -10
self.y = 0
elif (coords[0] < 0):
self.x = 10
self.y = 0
self.canvas.move(self.obs, self.x,self.y)
canvasGame.update()
time.sleep(0.05)
def createBarrel():
barrel = Barrel(canvasGame)
circle_thread = Thread(target=barrel.movement())
circle_thread.daemon = True
circle_thread.start()
createBarrel()
def plzmove():
moveplz = Thread(target=move())
moveplz.daemon = True
moveplz.start()
plzmove()
I tried creating threads but the problem continues, if there is a barrel moving, the player cant move (if there is nothing else moving, the player can move with freedom), also, the player movement is just an image being moved, any tip is appreciated, much love.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I am getting this error whilst trying to add collision to a game and I have gotten this error for now all I want is for the game to print yes when the target is hit if there better way to detect collision I'm all ears. anything helps.
TypeError: unbound method collide() must be called with Enemy instance as first argument (got type instance instead)
This error comes from this code
Enemy.collide(Bullets)
this is the entire code ~200 lines
import math
class Spacey(object):
def __init__(self,x,y,siz,col):
self.x = x
self.y = y
self.siz = siz
self.col = col
self.body_angle = -90
self.enabled = True
def see(self):
self.move()
self.render()
def show(self):
stroke(250)
point(self.x,self.y)
def move(self):
if(keyPressed and key == CODED):
if(keyCode == LEFT):
self.x += (sin(radians(self.body_angle))*2)
if(keyCode == RIGHT):
self.x -= (sin(radians(self.body_angle))*2)
if(keyCode == UP):
self.y += (sin(radians(self.body_angle))*2)
if(keyCode == DOWN):
self.y -= (sin(radians(self.body_angle))*2)
if(keyCode == SHIFT and self.enabled):
bullet_repeat = Bullets(self.x,self.y,5,stroke(113,195,0))
bullet.append(bullet_repeat)
self.enabled = False
else:
self.enabled = True
def render(self):
pushMatrix()
translate(self.x,self.y)
stroke(113,195,0)
strokeWeight(3)
fill(177,255,72)
beginShape()
vertex(self.x,self.y-40)
vertex(self.x-40,self.y+40)
vertex(self.x+40,self.y+40)
vertex(self.x,self.y-40)
endShape()
popMatrix()
class Bullets(object):
def __init__ (self,x,y,siz,col):
self.x = x
self.y = y
self.startX = int(x)
self.startY = y
self.siz = int(siz)
self.col = col
self.sx = x
def sx():
return int(self.x)
def siza(self):
return int(self.siz)
def colo():
stroke(113,195,0)
def see(self):
self.move()
self.render()
self.sx()
def show(self):
stroke(250)
point(self.x,self.y)
def move(self):
self.y = self.y - 5
for bullets in bullet:
if ((self.x-self.startX)**2 + (self.y-self.startY)**2) > 1000000000:
bullet.remove(bullets)
def render(self):
pushMatrix()
translate(self.x,self.y)
stroke(113,195,0)
beginShape()
circle(self.x,self.y+10,5)
endShape(CLOSE)
popMatrix()
class Enemy(object):
def __init__(self,x,y,siz,col):
self.x = int(x)
self.y = y
self.speed = 2
self.health = 1000
self.siz = int(siz)
self.col = col
def see(self):
self.move()
self.render()
def move(self):
spd = 2
bts = True
for i in range(0, 2, 500):
self.x += 2
if self.x == 500:
self.x = 2
def health(self):
healthy = 20
if collide == True:
health -= 1
if healthy == 0:
next_level()
healthy += 100
def render(self):
pushMatrix()
translate(self.x,self.y)
stroke(113,195,0)
strokeWeight(3)
fill(177,255,72)
beginShape()
vertex(self.x,self.y-40)
vertex(self.x-40,self.y+40)
vertex(self.x+40,self.y+40)
vertex(self.x,self.y-40)
endShape()
popMatrix()
def collide(self,other):
if(self.x + self.siz / 2 >= Bullets.sx() - Bullets.siz / 2 and self.x - self.siz / 2 <= Bullets.sx() + Bullets.siz / 2
and self.y + self.siz / 2 >= Bullets.y - Bullets.siza / 2 and self.y - self.siz / 2 <= Bullets.y + Bullets.siza / 2):
print("YES")
def get_accuracy():
for i in bullet:
accuracy = hitcount / bcount
if accuracy >= 90:
return 'AMAZING'
if accuracy >= 50:
return 'GOOD'
if accuracy >= 10:
return 'OKAY'
if accuracy < 10:
print('NOT GOOD')
spacey = Spacey(250,400, 20,color(113,195,0))
enemy = Enemy(0,20,20,color(113,195,0))
bullet = []
collidesss = []
levels = [1,2,3,4,5,6,7]
def reset():
spacey = spacey(250,400)
enemy = enemy(0,20)
def setup():
size(1000,1000)
def draw():
global bcount, hitcount
background(0,14,47)
for bullet_repeat in bullet:
bullet_repeat.see()
spacey.see()
enemy.see()
for i in bullet:
Enemy.collide(Bullets)
hitcount = 0
bcount = 0
for bullet_repeat in bullet:
bcount += 1
fill(255)
textSize(30)
text(bcount,920,950,)
text('Bullets shot:',730,950,)
This is now edited from the original
The code
for i in bullet:
Enemy.collide(Bullets)
should be
for i in bullet:
enemy.collide(Bullets)
Enemy is the class, enemy is an instance of the class.
In Python, class names are conventionally written with capital first letter, whereas instances/variables are written with lower case first letters.
I'm new to programming and would appreciate guidance/ feedback.
Below is a full working script:
I've managed to get the player sprite to be controlled by WASD, the asteroid sprite is also now rendered on the screen, with some physics to move it around. It should rebound off walls too but doesn't. But for some reason the update function isn't correctly calling on the Asteroid class, I believe - unless something else is wrong with it.
Greatly appreciate all help so ar and future guidance!
import arcade
import random
""" Universal variables """
SPRITE_SCALING_PLAYER = 0.5
SPRITE_SCALING_ASTEROID = 0.35
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
MOVEMENT_SPEED = 5
class Player(arcade.Sprite):
# PLAYER
def update(self):
# COLLISION
self.center_x += self.change_x
self.center_y += self.change_y
if self.left < 0:
self.left = 0
elif self.right > SCREEN_WIDTH - 1:
self.right = SCREEN_WIDTH - 1
if self.bottom < 0:
self.bottom = 0
elif self.top > SCREEN_HEIGHT - 1:
self.top = SCREEN_HEIGHT - 1
class Asteroid(arcade.Sprite):
# ASTEROID
def __init__(self, filename, sprite_scaling):
super().__init__(filename, sprite_scaling)
self.change_x = 0
self.change_y = 0
def update(self):
# Move the asteroid
self.center_x += self.change_x
self.center_y += self.change_y
# rebound
if self.left < 0:
self.change_x *= -1
if self.right > SCREEN_WIDTH:
self.change_x *= -1
if self.bottom < 0:
self.change_y *= -1
if self.top > SCREEN_HEIGHT:
self.change_y *= -1
# MAIN GAME CLASS
class MyGame(arcade.Window):
""" Our custom Window Class"""
def __init__(self):
""" Initializer """
# Call the parent class initializer
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Alien")
# Background image will be stored in this variable
self.background = ("space_bg.png")
# Variables that will hold sprite lists
self.all_sprite_list = ["ufo_sprite.png", "asteroid.gif"]
# Set up player
self.player_sprite = self.all_sprite_list[0]
# Set up asteroid
self.asteroid_sprite = self.all_sprite_list[1]
# Don't show the mouse cursor
self.set_mouse_visible(False)
# arcade.set_background_color(arcade.color.BLACK)
def setup(self):
""" Set up the game and initialize the variables. """
# background
self.background = arcade.load_texture(self.background)
# Sprite lists
self.all_sprite_list = arcade.SpriteList()
# Set up the player
self.player_sprite = Player("ufo_sprite.png", SPRITE_SCALING_PLAYER)
self.player_sprite.center_x = (SCREEN_WIDTH * 0.50)
self.player_sprite.center_y = (SCREEN_HEIGHT * 0.50)
self.all_sprite_list.append(self.player_sprite)
# Set up asteroid
self.asteroid_sprite = Asteroid("asteroid.gif", SPRITE_SCALING_ASTEROID)
Asteroid.center_x = random.randrange(SCREEN_WIDTH)
Asteroid.center_y = random.randrange(SCREEN_HEIGHT)
Asteroid.change_x = random.randrange(-4, 4)
Asteroid.change_y = random.randrange(-4, 4)
self.all_sprite_list.append(self.asteroid_sprite)
def on_draw(self):
# needed before other drawn elements
arcade.start_render()
# draw background
arcade.draw_texture_rectangle(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2,
SCREEN_WIDTH, SCREEN_HEIGHT, self.background)
# draw sprites
self.all_sprite_list.draw()
def update(self, delta_time):
""" Movement and game logic """
self.all_sprite_list.update()
def on_key_press(self, key, modifiers):
"""Called whenever a key is pressed. """
if key == arcade.key.W:
self.player_sprite.change_y = MOVEMENT_SPEED
elif key == arcade.key.S:
self.player_sprite.change_y = -MOVEMENT_SPEED
elif key == arcade.key.A:
self.player_sprite.change_x = -MOVEMENT_SPEED
elif key == arcade.key.D:
self.player_sprite.change_x = MOVEMENT_SPEED
# elif key == arcade.key.SPACE:
# self.player_sprite.change_x = MOVEMENT_SPEED
def on_key_release(self, key, modifiers):
"""Called when the user releases a key. """
if key == arcade.key.W or key == arcade.key.S:
self.player_sprite.change_y = 0
elif key == arcade.key.A or key == arcade.key.D:
self.player_sprite.change_x = 0
# elif key == arcade.key.SPACE:
# self.player_sprite.change_y = (SCREEN_HEIGHT * 0.005)
def main():
""" Main method """
window = MyGame()
window.setup()
arcade.run()
arcade.schedule(update, 1 / 80)
if __name__ == "__main__":
main()
Could you please tell us the exact problem (exception, sprites not moving as expected,...)
However, the code you provided gave me the following ideas:
calling the constructor of the inherited class
class Asteroid(arcade.Sprite):
def __init__(self):
super(Asteroid, self).__init__()
# or
arcade.Sprite.__init__(self)
more here (it's odd but I found nothing about calling the base constructor under the classes-inheritance-section in the official docs, maybe someone can provide something
using variables which don't exist or are created below
self.center_x += self.change_x * delta_time
self.center_y += self.change_y * delta_time
self.change_x is created below (so it does not exist at that time) and delta_time isn't anywhere else (maybe it's just an incomplete snippet?)
Do you really want to create an instance of Sprite after you made your own child class of Sprite (Asteroid)
self.asteroid_sprite = Asteroid("asteroid.gif", SPRITE_SCALING_ASTEROID)
instead of
self.asteroid_sprite = arcade.Sprite("asteroid.gif", SPRITE_SCALING_ASTEROID)
EDIT:
try to do this before assigning the variables in the Asteroid constructor:
def __init__(self, *args, **kwargs):
super(Asteroid, self).__init__(*args, **kwargs)
args and kwargs are placeholders for the things you are passing in below like the imagepath
Just what the title says...the ball sprite will often collide and ghost through the paddle and alien sprite causing it to stall or get stuck. Trying to figure out a way to fix this so the game operates better. This is my only attempt at making a game so far just trying to polish it more.
class Alien(games.Sprite):
"""
An alien which moves.
"""
image = games.load_image("crab.jpg")
def __init__(self, y, speed = 2, odds_change = 250):
""" Initialize alien. """
super(Alien, self).__init__(image = Alien.image,
x = games.screen.width/2,
y = y,
dx = speed)
self.odds_change = odds_change
self.timer = 0
def update(self):
""" Determine if direction needs to be reversed. """
if self.left < 0 or self.right > games.screen.width:
self.dx = -self.dx
elif random.randrange(self.odds_change) == 0:
self.dx = -self.dx
self.check_collide()
if self.timer > 0:
self.timer -= 1
##if ball hits alien add points
def check_collide(self):
for ball in self.overlapping_sprites:
if self.timer == 0:
self.timer = 100
Paddle.score.value+=10
ball.handle_collide()
else:
ball.handle_collide2()
class Paddle(games.Sprite):
##load up paddle sprite
image=games.load_image("platform.jpg")
score=games.Text(value=0, size=75, color = color.white, top=5,
right=games.screen.width - 20, is_collideable = False)
def __init__(self, theY=games.screen.height - 25):
super(Paddle, self).__init__(image=Paddle.image, angle = 0,
y = theY,
x=games.mouse.x,
left=20)
games.screen.add(Paddle.score)
def update(self):
self.x=games.mouse.x
if self.left<0:
self.x=0
if self.right>games.screen.width:
self.x=games.screen.width
self.check_collide()
def check_collide(self):
for ball in self.overlapping_sprites:
ball.handle_collide2()
class Ball(games.Sprite):
image=games.load_image("ball.jpg")
speed=2
def __init__(self, x=100, y=70):
super(Ball, self).__init__(image=Ball.image,
x=x, y=y,
dx=Ball.speed, dy=Ball.speed)
##make the ball bounce off walls
def update(self):
if self.right>games.screen.width:
self.dx=-self.dx
if self.left<0:
self.dx=-self.dx
if self.top<0:
self.dy=-self.dy
if self.bottom>games.screen.height:
self.end_game()
self.destroy()
##ball gets faster as score rises
def handle_collide(self):
if Paddle.score.value == 30:
self.dx *= 2
self.dy *= 2
if Paddle.score.value == 60:
self.dx *= 2
self.dy *= 2
self.dy=-self.dy
def handle_collide2(self):
self.dy=-self.dy
I have asked multiple people I know who create games with python but none of them could come up with a better solution.
I'm a college student. I'm in my second comp sci class and we haven't got much past simply making classes and functions within them so I haven't really been able to make much use of the complicated jargon I've found on the internet.
I'm making a roach infestation sim, and I need to be able to have a "roach" class be able to detect where a "food" class is in a window. My teacher told me that my best shot might be to make another mastermind-like class that is a middle man between the two, but I don't really know how that would work. Can anyone help me out? I'm using Python through Calico. Here's what I have of the roach class (EDIT: guess I should show the main() etc too):
class Roach:
def __init__(self, win, placex, placey):
self.timer = 320 + (10 *(int(10 *random.random())))
self.speed = 0.2
self.heading = 360
self.win = win
self.x = placex
self.y = placey
self.body = self.makeBody()
self.body.draw(self.win)
def __str__(self):
t = "Roach at ("+str(self.x)+","+str(self.y)+")"
return t
def makeBody(self):
body = Rectangle((-5,-5),(5,5))
body.setFill(Color('Brown'))
body.moveTo(self.x,self.y)
return body
def move(self, win):
self.x = self.x + self.speed *sin(self.heading)
self.y = self.y + self.speed *cos(self.heading)
self.body.moveTo(self.x,self.y)
self.avoid(win)
def avoid(self, win):
Border = False
if self.x >= win.getWidth():
self.setHeading(random.randrange(91, 269))
self.x = win.getWidth() - 1
Border = True
elif self.x <= 0:
self.setHeading(random.randrange(271, 449))
self.x = 1
Border = True
elif self.y >= win.getHeight():
self.setHeading(random.randrange(1, 179))
self.y = win.getHeight() - 1
Border = True
elif self.y <= 0:
self.setHeading(random.randrange(181, 359))
self.y = 1
Border = True
return Border
#Getters
def getSpeed(self):
return self.speed
def getHeading(self):
return self.heading
def getX(self):
return self.x
def getY(self):
return self.y
#Setters
def setSpeed(self, speed):
self.speed = speed
def setHeading(self, heading):
self.heading = heading
self.body.rotateTo(self.heading)
def setX(self, x):
self.x = x
def setY(self, y):
self.y = y
def main():
win = Window(400, 400)
win.setBackground(Color("White"))
Rpop = []
Wpop = []
i = 320
menu(win, Rpop, Wpop)
while getKeyPressed() != 'Escape':
for roach in Rpop:
if roach.avoid(win) == True:
roach.avoid(win)
elif i % roach.timer == 0:
roach.setHeading(360*random.random())
roach.move(win)
if getKeyPressed() == 'm':
menu(win, Rpop, Wpop)
i = i + 1
def menu(win, Rpop, Wpop):
while getKeyPressed() != 's':
if getKeyPressed() == 'r':
Rpop.append(Roach(win,getMouseNow()[0],getMouseNow()[1]))
if getKeyPressed() == 'w':
point1 = getMouse()
dot1 = Circle((point1[0],point1[1]), 3)
dot1.draw(win)
point2 = getMouse()
dot2 = Circle((point2[0],point2[1]), 3)
dot2.draw(win)
Wpop.append(Wall(win, point1[0], point1[1], point2[0], point2[1]))
return
main()
Sorry for the lack of comments and likely juvenile programming. Thank you so much.
Here's a sort of rough outline of how you might use an additional "Master" class to allow two other classes to communicate as is alluded to in the OP:
class Master():
...
def is_food_there(self, coords):
for food_instance in self.food_instances:
if coords == food_instance.coords:
return True
class Food():
def __init__(self, master_instance):
self.coords = ###some coordinates or whatever
master_instance.food_instances.append(self) ### register this food with master
class Roach():
def __init__(self, master_instance):
self.master_instance = master_instance
...
def move(self, newlocation):
if( self.master_instance.is_food_there(newlocation) ): ### check with master for food coords
###do something
The idea is that the we have a Master class which is essentially a container for a list of Food instances, and Roach class knows which Master instance it belongs to, so it can access that master's "is_food_there" function which in turn looks through the Food instances that belong to it. The Master class is "the man in the middle" in this example.