Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
Help with actions for SpriteNodes
-
I'm working on a space shooter game and I can't figure out how to get the 'enemy' spaceship to wrap around to the other side of the screen. Here's my code so far. Hope someone can give some suggestions.
from scene import * class MyScene (Scene): def setup(self): self.background_color = 'midnightblue' self.ship = SpriteNode('spc:PlayerShip1Orange') self.ship.position = self.size/2 self.add_child(self.ship) self.badGuy = SpriteNode('spc:EnemyBlack4') self.bx,self. by = self.size self.by -= 50 self.bx += 50 self.badGuy.position = (self.bx, self.by) self.add_child(self.badGuy) def update(self): x,y,z = gravity() pos = self.ship.position pos += (x * 15, y * 15) pos.x = max(0, min(self.size.w, pos.x)) pos.y = max(0, min(self.size.h, pos.y)) self.ship.position = pos def resetBad(self): self.badGuy.position = (self.bx, self.by) def touch_began(self, touch): resetBadGuy = Action.call(self.resetBad()) laser = SpriteNode('spc:LaserBlue9', position=self.ship.position, z_position=-1, parent=self) laser.run_action(Action.sequence(Action.move_by(0,1000), Action.remove())) self.badGuy.run_action(Action.repeat(Action.sequence(Action.move_by(-818, 0, 5), resetBad), -1)) print self.badGuy.position.x #self.badGuy.position = (self.bx, self.by) run(MyScene(), PORTRAIT)
-
I am not sure if this is what you wanted but in
update(self)
, comment out two lines and two new ones:#pos.x = max(0, min(self.size.w, pos.x)) #pos.y = max(0, min(self.size.h, pos.y)) pos.x %= self.size.w pos.y %= self.size.h
EDIT: Oops.. That changes the good guy. Still interesting to see how to wrap around.
The first line of
touch_begin()
is throwing an exception so change that line to remove()
.Then a few lines further down, change
resetBad
toself.resetBad
. That helps a little bit. -
I made your changes, you're right, I'm not getting anymore errors but still am not able to get it to wrap around. I think maybe I could use another action.move_to() with a timing mode that will get it there instantly, so no one could see it but I'm not sure where to find documentation on the different timing modes. Any help?
from scene import *
class MyScene (Scene):
def setup(self):
self.background_color = 'midnightblue'
self.ship = SpriteNode('spc:PlayerShip1Orange')
self.ship.position = self.size/2
self.add_child(self.ship)
self.badGuy = SpriteNode('spc:EnemyBlack4')
self.bx,self. by = self.size
self.by -= 50
self.bx += 50
self.badGuy.position = (self.bx, self.by)
self.add_child(self.badGuy)def update(self): x,y,z = gravity() pos = self.ship.position pos += (x * 15, y * 15) pos.x = max(0, min(self.size.w, pos.x)) pos.y = max(0, min(self.size.h, pos.y)) self.ship.position = pos def resetBad(self): self.badGuy.position = (self.bx, self.by) def touch_began(self, touch): resetBadGuy = Action.call(self.resetBad) laser = SpriteNode('spc:LaserBlue9', position=self.ship.position, z_position=-1, parent=self) laser.run_action(Action.sequence(Action.move_by(0,1000), Action.remove())) self.badGuy.run_action(Action.repeat(Action.sequence(Action.move_by(-818, 0, 5), self.resetBad), -1)) print self.badGuy.position.x #self.badGuy.position = (self.bx, self.by)
run(MyScene(), PORTRAIT)
-
Yay! I finally figured out how to get the ship to wrap around. Now I need to figure out how to detect collisions...
from scene import *
class MyScene (Scene):
def bad_guy(self):
self.badGuy.run_action(Action.repeat(Action.sequence(Action.move_by(-818, 0, 5), Action.move_by(818, 0, 0.001)), -1))def setup(self): self.background_color = 'midnightblue' self.ship = SpriteNode('spc:PlayerShip1Orange') self.ship.position = self.size/2 self.add_child(self.ship) self.badGuy = SpriteNode('spc:EnemyBlack4') self.bx,self. by = self.size self.by -= 50 self.bx += 50 self.badGuy.position = (self.bx, self.by) self.add_child(self.badGuy) self.bad_guy() def update(self): x,y,z = gravity() pos = self.ship.position pos += (x * 15, y * 15) pos.x = max(0, min(self.size.w, pos.x)) pos.y = max(0, min(self.size.h, pos.y)) self.ship.position = pos def touch_began(self, touch): laser = SpriteNode('spc:LaserBlue9', position=self.ship.position, z_position=-1, parent=self) laser.run_action(Action.sequence(Action.move_by(0,1000), Action.remove()))
run(MyScene(), PORTRAIT)
-
Add this code to the bottom of update():
for child in self.children: if child not in (self.ship, self.badGuy) and child.frame in self.badGuy.frame: exit("It's a hit!")
The last paragraph of http://omz-software.com/pythonista/docs/ios/scene.html#geometry talks about a better approach to hit detection. My code above requires that the bullet is completely inside the bad guy's frame. It is the difference between Rect.contains_rect() and Rect.intersects().
-
Thanks so much. It works perfectly.