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.
Removing missile, when goes off screen
-
I am using the scene module to make a game. When I hit a button, I have a missile moving up the screen. When it goes off the screen, I would like to remove it from my array and memory, to clear up memory and since in the game the missile is gone.
I have tried many things and it does not seem to remove it right away, and then tries to remove more than one. Not sure what I am doing wrong. At line 80.
Here is the Gist: https://gist.github.com/cb0ac079b7351e2b59e980237a546152
# Created by: Mr. Coxall # Created on: Sep 2016 # Created for: ICS3U # This program is the first file in a multi-scene game template # This template is meant to be used with the Xcode from scene import * import ui from numpy import random from copy import deepcopy class FirstScene(Scene): def setup(self): # this method is called, when user moves to this scene self.size_of_screen = deepcopy(self.size) self.center_of_screen = deepcopy(self.size/2) self.left_button_down = False self.right_button_down = False self.ship_move_speed = 40.0 self.missiles = [] self.aliens = [] self.alien_attack_rate = 1 self.alien_attack_speed = 20.0 # add blue background color self.background = SpriteNode(position = self.size / 2, color = (0.61, 0.78, 0.87), parent = self, size = self.size) spaceship_position = deepcopy(self.center_of_screen) spaceship_position.y = 100 self.spaceship = SpriteNode('spc:PlayerShip1Orange', parent = self, position = spaceship_position) left_button_position = deepcopy(self.center_of_screen) left_button_position.x = 75 left_button_position.y = 75 self.left_button = SpriteNode('iob:arrow_left_a_256', parent = self, scale = 0.5, position = left_button_position, alpha = 0.5) right_button_position = deepcopy(self.center_of_screen) right_button_position.x = 200 right_button_position.y = 75 self.right_button = SpriteNode('iob:arrow_right_a_256', parent = self, scale = 0.5, position = right_button_position, alpha = 0.5) fire_button_position = deepcopy(self.size) fire_button_position.x = fire_button_position.x - 75 fire_button_position.y = 75 self.fire_button = SpriteNode('iob:disc_256', parent = self, scale = 0.5, position = fire_button_position, alpha = 0.5) def update(self): # this method is called, hopefully, 60 times a second # move spaceship if button down if self.left_button_down == True: spaceshipMove = Action.move_by(-1*self.ship_move_speed, 0.0, 0.1) self.spaceship.run_action(spaceshipMove) if self.right_button_down == True: spaceshipMove = Action.move_by(self.ship_move_speed, 0.0, 0.1) self.spaceship.run_action(spaceshipMove) # check every update if a missile is off screen print('A: ' + str(range(len(self.missiles)))) for missile_index in range(len(self.missiles)): if self.missiles[missile_index].position.y > self.size_of_screen.y - 100: #self.missiles[missile_index].remove_all_actions() #self.missiles[missile_index].remove_from_parent() print('B: ' + str(missile_index) + ' ' + str(len(self.missiles))) #print(missile_index) self.missiles.remove(missile_index) #print('one success') break #print(len(self.missiles)) def touch_began(self, touch): # this method is called, when user touches the screen # check if left or right button is down if self.left_button.frame.contains_point(touch.location): self.left_button_down = True if self.right_button.frame.contains_point(touch.location): self.right_button_down = True def touch_moved(self, touch): # this method is called, when user moves a finger around on the screen pass def touch_ended(self, touch): # this method is called, when user releases a finger from the screen # if I removed my finger, then no matter what spaceship # should not be moving any more self.left_button_down = False self.right_button_down = False # if fire button pressed, create a new missile if self.fire_button.frame.contains_point(touch.location): self.create_new_missile() def create_new_missile(self): # when the user hits the fire button missile_start_position = deepcopy(self.spaceship.position) missile_start_position.y = 100 missile_end_position = deepcopy(self.size) missile_end_position.x = missile_start_position.x self.missiles.append(SpriteNode('spc:Fire1', position = missile_start_position, parent = self)) # make missile move forward missileMoveAction = Action.move_to(missile_end_position.x, missile_end_position.y + 100, 1.0) self.missiles[len(self.missiles)-1].run_action(missileMoveAction) # ..use when deploying app for Xcode and the App Store main_view = ui.View() scene_view = SceneView(frame = main_view.bounds, flex = 'WH') main_view.add_subview(scene_view) scene_view.scene = FirstScene() main_view.present(hide_title_bar = True, animated = False) ~~~ Thanks
-
If you are really concerned about memory there is a lot more in your code that can be cleaned up, mainly unnecessary variables, etc. But if you need help with that then we can go over it after.
As to the rockets not deleting correctly, I get an error before it can even delete due to non-existent indecies in the list (due to the list being modified from in the loop that is not really friendly with your code). To resolve that I completely changed yourfor
-loop to the following:for i, missile in enumerate(self.missiles): print(i, missile.position) if missile.position.y > self.size_of_screen.y - 100: missile.remove_from_parent() self.missiles.remove(missile)
Also
Node.remove_from_parent()
needs to be called for the object to be removed from the render list. -
@Cethric
Works great.
Thanks -
You might also run "Check Style" and "Analyze (PyFlakes)" from the run menu. Those two tools mention a few items that would be worth fixing.
-
Another take...
# Created by: Mr. Coxall # Created on: Sep 2016 # Created for: ICS3U # This program is the first file in a multi-scene game template # This template is meant to be used with the Xcode import scene import ui Action = scene.Action class FirstScene(scene.Scene): def setup(self): # this method is called, when user moves to this scene self.left_button_down = False self.right_button_down = False self.ship_move_speed = 40.0 self.missiles = [] # self.aliens = [] # self.alien_attack_rate = 1 # self.alien_attack_speed = 20.0 # add blue background color scene.SpriteNode(position=self.size / 2, color=(0.61, 0.78, 0.87), parent=self, size=self.size) position = scene.Point(self.size.x / 2, 100) self.spaceship = scene.SpriteNode('spc:PlayerShip1Orange', parent=self, position=position) self.left_button = scene.SpriteNode('iob:arrow_left_a_256', parent=self, scale=0.5, position=scene.Point(75, 75), alpha=0.5) self.right_button = scene.SpriteNode('iob:arrow_right_a_256', parent=self, scale=0.5, position=scene.Point(200, 75), alpha=0.5) position = scene.Point(self.size.x - 75, 75) self.fire_button = scene.SpriteNode('iob:disc_256', parent=self, scale=0.5, position=position, alpha=0.5) def update(self): # this method is called, hopefully, 60 times a second # move spaceship if button down if self.left_button_down: self.spaceship.run_action(Action.move_by(-self.ship_move_speed, 0.0, 0.1)) if self.right_button_down: self.spaceship.run_action(Action.move_by(self.ship_move_speed, 0.0, 0.1)) # check every update if a missile is off screen print('A: {}'.format(len(self.missiles))) for i, missile in enumerate(self.missiles): print(i, missile.position) if missile.position.y > self.size.y - 100: missile.remove_from_parent() self.missiles.remove(missile) break def touch_began(self, touch): # this method is called, when user touches the screen # check if left or right button is down self.left_button_down = touch.location in self.left_button.frame self.right_button_down = touch.location in self.right_button.frame def touch_moved(self, touch): # this method is called, when user moves a finger around on the screen pass def touch_ended(self, touch): # this method is called, when user releases a finger from the screen # if I removed my finger, # then no matter what spaceship should not be moving any more self.left_button_down = False self.right_button_down = False # if fire button pressed, create a new missile if touch.location in self.fire_button.frame: self.create_new_missile() def create_new_missile(self): # when the user hits the fire button missle = scene.SpriteNode('spc:Fire1', position=self.spaceship.position, parent=self) missle.run_action(Action.move_to(self.spaceship.position.x, self.size.y + 100, 1.0)) self.missiles.append(missle) # ..use when deploying app for Xcode and the App Store if __name__ == '__main__': main_view = ui.View() scene_view = scene.SceneView(frame=main_view.bounds, flex='WH') scene_view.scene = FirstScene() main_view.add_subview(scene_view) main_view.present(hide_title_bar=True, animated=False) # scene_view = scene.SceneView() # scene_view.scene = FirstScene() # scene_view.present(hide_title_bar = True, animated = False) # scene.run(FirstScene())