omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular
    1. Home
    2. Tonnoaw

    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.


    • Profile
    • Following 0
    • Followers 0
    • Topics 3
    • Posts 9
    • Best 3
    • Controversial 0
    • Groups 0

    Tonnoaw

    @Tonnoaw

    3
    Reputation
    525
    Profile views
    9
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    Tonnoaw Unfollow Follow

    Best posts made by Tonnoaw

    • RE: How to create effect

      Thanks guys, I will study about shader and effect more Thanks!

      posted in Pythonista
      Tonnoaw
      Tonnoaw
    • Try out my space shooter game, And I want your suggestions!

      I created 2D space shooting game
      I want your suggestion from any experts or anyone. I have just learned Python for a month and I want some suggestions to improve my coding skills.
      I test and run this script on iPad

      from scene import *
      import sound
      import random
      import math
      A = Action
      
      class Laser(SpriteNode):
          def __init__(self, txture, object, **kwargs):
              SpriteNode.__init__(self, txture, **kwargs)
              self.shooter = object
      
      class Heart(SpriteNode):
          def __init__(self, **kwargs):
              SpriteNode.__init__(self, 'plf:HudHeart_full', **kwargs)
      
      class Enemy(SpriteNode):
          def __init__(self, txture, **kwargs):
              SpriteNode.__init__(self, txture, **kwargs)
              self.time = 0
              allow_move = random.choice(('x', 'y'))
              self.allow_move = allow_move
              
      class MyScene (Scene):
          def setup(self):
              self.move = 'up'; self.player_score = 0; self.touch_id_location = {}; self.touched = False;
              self.laser_on_screen = []; self.enemy_on_screen = []; self.player_health = 100; self.game_playing = True
              self.heart_on_screen = []; self.shown = False
              for x in range(int((self.size.x / 128)) + 1):
                  for y in range(int((self.size.y / 128)) + 1):
                      bg = SpriteNode(Texture('spc:BackgroundBlue'), position = (x * 128, y *128)); self.add_child(bg)
              self.score = LabelNode(f'Score: {self.player_score}', ('<System-Bold>', 30), position = (120, self.size.h - 30)); self.add_child(self.score)
              self.player_health_label = LabelNode(f'Health: {self.player_health}', ('<System-Bold>', 30), position = (self.size.w - 120, self.size.h - 30)); self.add_child(self.player_health_label)
              self.player = SpriteNode(Texture('spc:PlayerShip1Green'), position = (self.size.w / 2, self.size.h / 2))
              self.add_child(self.player)
              self.joy_layout = SpriteNode(Texture('iow:ios7_circle_outline_256'), position = (160, 160), alpha = 0.25, scale = 1)
              self.add_child(self.joy_layout)
              self.shoot_button = SpriteNode(Texture('iow:ios7_circle_filled_256'), position = (self.size.w - 160, 160), scale = 0.5, alpha = 0.25); self.add_child(self.shoot_button)
          
          def update(self):
              if self.game_playing:
                  if self.touched:
                      touch_location = self.touch_id_location.get(self.touch_in_joy)
                      self.move_ship()
                  if len(self.laser_on_screen) > 0:
                      for laser in self.laser_on_screen:
                          if laser.position.x > self.size.w or laser.position.y > self.size.h or laser.position.x < 0 or laser.position.y < 0 :
                              self.laser_on_screen.remove(laser)
                              laser.remove_from_parent()
                  self.spawn_enemy()
                  self.check_laser_collision()
                  self.score.text = f'Score: {self.player_score}'
                  self.player_health_label.text = f'Health: {self.player_health}'
                  self.move_enemy()
                  self.spawn_heart_pack()
                  self.check_player_get_heart()
              if self.player_health <= 0:
                  self.game_playing = False
                  self.joy_layout.remove_from_parent()
                  self.shoot_button.remove_from_parent()
                  for enemy in self.enemy_on_screen:
                      enemy.remove_from_parent()
                  for laser in self.laser_on_screen:
                      laser.remove_from_parent()
                  for heart in self.heart_on_screen:
                      heart.remove_from_parent()
                  self.player.remove_from_parent()
                  if not self.shown:
                      self.lose_scene()
                      self.shown = True
          
          def lose_scene(self):
              sound.play_effect('arcade:Explosion_4')
              self.lose_label = LabelNode('LOSE!', ('<System-Bold>', 60), position = (self.size.w /2, self.size.h / 2)); self.add_child(self.lose_label)
              self.score_label = LabelNode(f'Score: {self.player_score}', ('<System-Bold>', 50), position = (self.size.w /2, self.size.h / 2 - 100)); self.add_child(self.score_label)
                  
          
          def check_player_get_heart(self):
              for heart in self.heart_on_screen:
                  if self.player.position in heart.frame:
                      self.heart_on_screen.remove(heart)
                      heart.remove_from_parent()
                      sound.play_effect('arcade:Powerup_1')
                      self.player_health += 15
                              
          def touch_began(self, touch):
              self.touch_id_location[touch.touch_id] = touch.location
              if touch.location in self.joy_layout.frame and not self.touched:
                  self.joy_layout.run_action(A.sequence(A.scale_to(1.25, 0.025)))
                  self.joy_layout.position = touch.location
                  self.touch_in_joy = touch.touch_id
                  self.joy = SpriteNode(Texture('iow:ios7_circle_filled_256'), position = touch.location, alpha = 0.25, scale = 0.25)
                  self.add_child(self.joy)
                  self.test = SpriteNode(Texture('iow:ios7_circle_filled_256'), position = touch.location, scale = 0.25)
                  self.add_child(self.test)
                  self.touched = True
                  
              if touch.location in self.shoot_button.frame:
                  sound.play_effect('digital:Laser2')
                  self.shoot_button.run_action(A.sequence(A.scale_to(0.4, 0.05), A.scale_to(0.5, 0.05)))
                  self.shoot_laser(self.player.position, 'spc:LaserBlue9', self.player, self.move)
                  
                  
          def touch_moved(self, touch):
              self.touch_id_location[touch.touch_id] = touch.location
              try:
                  if touch.touch_id == self.touch_in_joy:
                      self.joy.position = touch.location
              except AttributeError:
                  pass
                  
          def touch_ended(self, touch):
              self.touch_id_location.pop(touch.touch_id)
              try:
                  if touch.touch_id == self.touch_in_joy:
                      self.joy.remove_from_parent()
                      self.joy_layout.run_action(A.sequence(A.scale_to(1, 0.025)))
                      self.joy_layout.position = (160, 160)
                      self.touched = False
                      self.test.remove_from_parent()
              except AttributeError:
                  pass
                  
          def move_ship(self):
              move_attributes = {
                  'up': ((0, 6), math.radians(0)),
                  'down': ((0, -6), math.radians(180)),
                  'left': ((-6, 0), math.radians(90)),
                  'right': ((6, 0), math.radians(270))
              }
              touch_position = self.touch_id_location.get(self.touch_in_joy)
              if touch_position not in self.test.frame:
                  if self.test.position.x - 64 < touch_position.x < self.test.position.x + 64:
                      if touch_position.y > self.test.position.y:
                          self.move = 'up'
                      else:
                          self.move = 'down'
                  if self.test.position.y - 64 < touch_position.y < self.test.position.y + 64:
                      if touch_position.x > self.test.position.x:
                          self.move = 'right'
                      else:
                          self.move = 'left'
                          
              m = move_attributes.get(self.move)
              try:
                  x = max(0, min(self.size.w, self.player.position.x + m[0][0]))
                  y = max(0, min(self.size.y, self.player.position.y + m[0][1]))
                  self.player.position = (x, y)
                  self.player.run_action(A.sequence(A.rotate_to(m[1], 0.025)))
              except TypeError:
                  pass
          
          def shoot_laser(self, position, txture, object, orient):
              if object == self.player:
                  laser_attributes = {
                      'up': ((0, 500), math.radians(0), (0, 64)),
                      'down': ((0, -500), math.radians(180), (0, -64)),
                      'left': ((-500, 0), math.radians(90), (-64, 0)),
                      'right': ((500, 0), math.radians(270), (64, 0))
                  }
              else:
                  laser_attributes = {
                      'up': ((0, 250), math.radians(0), (0, 64)),
                      'down': ((0, -250), math.radians(180), (0, -64)),
                      'left': ((-250, 0), math.radians(90), (-64, 0)),
                      'right': ((250, 0), math.radians(270), (64, 0))
                      }
              l = laser_attributes.get(orient)
              x, y = l[0]
              laser = Laser(txture, object); laser.position = (object.position.x + l[2][0], object.position.y + l[2][1])
              self.laser_on_screen.append(laser); self.add_child(laser)
              laser.run_action(A.sequence(A.rotate_to(l[1], 0.00001), A.repeat_forever(A.move_by(x, y))))
          
          def spawn_enemy(self):
              self.difficulty = 0.008 + self.player_score * 0.0000002
              if random.random() < self.difficulty and len(self.enemy_on_screen) <= 8:
                  index = random.choice([1, 0])
                  coor = [(random.uniform(200, self.size.w), random.uniform(self.size.h - 200, self.size.h)), (random.uniform(200, self.size.w - 200), random.uniform(0 ,200))]
                  x, y = coor[index]
                  txture = random.choice(['spc:EnemyGreen4', 'spc:EnemyBlack4', 'spc:EnemyBlue4'])
                  enemy = Enemy(txture)
                  if index == 0:
                       enemy.position = (self.size.w / 2, self.size.h + 48)
                  else:
                      enemy.position = (self.size.w / 2, -48)
                  enemy.run_action(A.sequence(A.move_to(x, y, 1)))
                  self.add_child(enemy) 
                  self.enemy_on_screen.append(enemy)
          
          def spawn_heart_pack(self):
              difficulty = self.difficulty * 0.05
              if random.random() < difficulty:
                  posX, posY =  (random.uniform(self.size.w - 300, 300), random.uniform(self.size.h - 300, 300))
                  self.heart = Heart(); self.heart.position = (posX, posY); self.heart.scale = 0.8
                  self.add_child(self.heart); self.heart_on_screen.append(self.heart)
                 
          def check_laser_collision(self):
              for laser in self.laser_on_screen:
                  for enemy in self.enemy_on_screen:
                      if laser.position in enemy.frame:
                          self.enemy_on_screen.remove(enemy)
                          enemy.remove_from_parent()
                          try:
                              self.laser_on_screen.remove(laser)
                          except ValueError:
                              pass
                          laser.remove_from_parent()
                          self.player_score += 80
                          sound.play_effect('arcade:Explosion_1')
                          self.explosion_effect(enemy.position)
                  if laser.position in self.player.frame and (laser.shooter in self.enemy_on_screen):
                      sound.play_effect('game:Error')
                      try:
                          self.laser_on_screen.remove(laser)
                      except ValueError:
                          pass
                          
                      self.player_health -= 5
                      laser.remove_from_parent()
                      for i in range(6):
                          particle = SpriteNode(Texture('spc:MeteorBrownMed2'), position = self.player.position, scale=random.uniform(0.3, 0.5))
                          actions1 = [A.group(A.move_by(random.uniform(-64, 64), random.uniform(-64, 64), random.uniform(0.4, 0.9)), A.rotate_by(random.uniform(1, 3), 0.4)), A.wait(0.4), A.fade_to(0, 0.3)] 
                          self.add_child(particle); particle.run_action(A.sequence(actions1))
                          
                         
          def explosion_effect(self, position):
              index = 0
              time = [0.0, 0.1, 0.2, 0.3, 0.4]
              for i in range(4):
                  explosion_texture = random.choice(('shp:Explosion01', 'shp:Explosion04', 'shp:Explosion00'))
                  ex_position = (position.x + random.uniform(-24, 24), position.y + random.uniform(-24, 24))
                  pa_position = (position.x + random.uniform(-16, 16), position.y + random.uniform(-16, 16))
                  actions = [A.wait(time[index]), A.fade_to(1, 0.04), A.wait(0.06), A.remove()]
                  exploded = SpriteNode(Texture(explosion_texture), position = ex_position, scale = random.uniform(0.25, 0.5), alpha = 0)
                  self.add_child(exploded); exploded.run_action(A.sequence(actions))
                  index += 1
                  particle = SpriteNode(Texture('spc:MeteorBrownMed2'), position = pa_position, scale=random.uniform(0.5, 0.8))
                  actions1 = [A.group(A.move_by(random.uniform(-64, 64), random.uniform(-64, 64), random.uniform(0.4, 0.9)), A.rotate_by(random.uniform(1, 3), 0.4)), A.wait(0.4), A.fade_to(0, 0.3)] 
                  self.add_child(particle); particle.run_action(A.sequence(actions1))
      
          def move_enemy(self):
              orient = ''
              for enemy in self.enemy_on_screen:
                  if not self.can_shoot_laser(enemy):      
                      if enemy.position.y > self.player.position.y and enemy.allow_move == "y":
                          orient = 'down'
                          self.enemy_moving(orient, enemy)
                      elif enemy.allow_move == 'y':
                          orient = 'up'
                          self.enemy_moving(orient, enemy)
                      if enemy.position.x > self.player.position.x and enemy.allow_move == "x":
                          orient = 'left'
                          self.enemy_moving(orient, enemy)
                      elif enemy.allow_move == 'x':
                          orient = 'right'
                          self.enemy_moving(orient, enemy)
                          
                  
          def enemy_moving(self, orient, enemy):
              move_attributes = {
                  'up': ((0, 2.5), math.radians(0)),
                  'down': ((0, -2.5), math.radians(180)),
                  'left': ((-2.5, 0), math.radians(90)),
                  'right': ((2.5, 0), math.radians(270))
              }
              try:
                  m = move_attributes.get(orient)
                  x = max(0, min(self.size.w, enemy.position.x + m[0][0]))
                  y = max(0, min(self.size.y, enemy.position.y + m[0][1]))
                  enemy.position = (x, y)
                  enemy.run_action(A.sequence(A.rotate_to(m[1], 0.025)))
              except (TypeError):
                  pass
                       
          def can_shoot_laser(self, enemy):
              aligned = False
              if self.player.position.x - 64 < enemy.position.x < self.player.position.x + 64:
                  enemy.time += 1
                  aligned = True
                  if enemy.position.y > self.player.position.y:
                      orient = 'down'
                  else:
                      orient = 'up'
                      
              if self.player.position.y - 64 < enemy.position.y < self.player.position.y + 64:
                  enemy.time += 1
                  aligned = True
                  if enemy.position.x > self.player.position.x:
                      orient = 'left'
                  else:
                      orient = 'right'
          
              if enemy.time > 60:
                  enemy.time = 0
                  self.shoot_laser(enemy.position, 'spc:LaserRed9', enemy, orient)
                  sound.play_effect('arcade:Laser_5')
                  if enemy.allow_move == 'x':
                      enemy.allow_move = 'y'
                  else:
                      enemy.allow_move = 'x'
              return aligned
              
      if __name__ == '__main__':
          run(MyScene(), show_fps=False) ```
      posted in Pythonista
      Tonnoaw
      Tonnoaw
    • I created 2D minesweeper game, Try out!

      I created 2D minesweeper game
      I've learned Python for a month and I decided to create 2D minesweeper game using scene module in Pythonista. I want some recommendations from any experts to make my code more cleaner and remove some unnecessary steps.
      Also try out my game :)

      from scene import *
      import sound
      import random
      
      #randomly install the mines on the board
      def setTheMine(board):
              for i in range(int(len(board))):
                  board[random.randint(0,len(board) - 1)][random.randint(0,len(board) - 1)] = "#"
              return board
              
      class App(Scene):    
          def setup(self):
              self.x, self.y = 0, 0
              #turn cheat to True to see the mines while playing
              self.cheat = False
              #create 2d matrix board
              # '-' = empty space and '#' = mine
              self.board = [["-" for i in range(10)] for i in range(10)]
              self.background_color = '#828adb'
              #install the mine
              self.board = setTheMine(self.board)
              #assign tile coordinates  
              self.tileDict = {}
              for row in range(len(self.board)):
                  for block in range(len(self.board[0])):
                      posist = str(block)+str(row)
                      posX_value = int(self.size.w / 2) - int((len(self.board) * 48) / 2) + (48 * block)
                      posY_value = int(self.size.h / 2) + int((len(self.board) * 48) / 2) - (48 * row)
                      x = self.tileDict.setdefault(posist, (posX_value, posY_value))
              #tile color according values
              self.tileColor = {
                  "0": 'pzl:Green3',
                  "1": 'pzl:Blue3',
                  "2": 'pzl:Yellow3',
                  "3": 'pzl:Red3',
                  "4": 'pzl:Red3',
                  "5": 'pzl:Red3',
                  "6": 'pzl:Red3',
                  "7": 'pzl:Red3',
                  "-": 'pzl:Gray3',
                  "#": 'pzl:Gray3'
              }
              self.labelFont = ('Adidas Unity', 50)
              self.gameStart = True
              #display 2D graphic board
              self.displayBoard()
              
          def touch_began(self, touch):
              self.x, self.y = touch.location
              
          def displayBoard(self):
              grid = Node(parent=self)
              row1 = 0
              for row in self.board:
                  column = 0
                  for block in row:
                      posX , posY = self.tileDict.get(str(column)+str(row1))
                      tile = SpriteNode(Texture(self.tileColor.get(block)), position = (posX, posY), scale = 1.5)
                      grid.add_child(tile)
                      if self.cheat:
                          if block == '#':
                              self.mine = SpriteNode(Texture('emj:Bomb'), position = (posX, posY), scale = 0.5)
                              self.add_child(self.mine)
                      if block is not "-" and block is not "#":
                          self.mineLabel = LabelNode(self.board[row1][column], self.labelFont, position = (posX, posY), scale = 0.5)
                          self.add_child(self.mineLabel)
                      column += 1
                  row1 += 1
                               
          def update(self):
              #check for touch input. is touch input on the board 
              found = False
              for y in range(len(self.board)):
                  for x in range(len(self.board[0])):
                      testCase = str(x)+str(y)
                      #x and y coordinates for each tile
                      testPosX, testPosY = self.tileDict.get(testCase)
                      if testPosX - 24 < self.x < testPosX + 24 and testPosY - 24 < self.y < testPosY + 24: 
                          self.x, self.y = 0, 0
                          sound.play_effect('8ve:8ve-beep-shinymetal')
                          if self.gameStart:
                              found = True
                          #tile that user touched
                          tileSelected = testCase
                          break
                  if found:
                      break
              if found:
                  #check if user touched on the mine
                  if self.board[int(tileSelected[1])][int(tileSelected[0])] is "#":
                      self.gameStart = False
                      self.gameStatus = 'lose'
                  else:
                  #else reveal the number of mines that surround the tile
                      if self.board[int(tileSelected[1])][int(tileSelected[0])] is not "#":
                          self.board = zeroScanning(self.board, (int(tileSelected[0]), int(tileSelected[1])))
                  self.foundSpace = False
                  #check if all tiles are revealed
                  for row in self.board:
                      for tile in row:
                          if tile is '-':
                              self.foundSpace = True
                              break
                      if self.foundSpace:
                          break
                  #if there is no empty tile left = win!
                  if self.foundSpace == False:
                      self.gameStatus = 'win'
                      self.gameStart = False
                  if self.gameStart:
                      self.displayBoard()
                  #if game ends
                  else:
                      #reveals the mine
                      self.cheat = True
                      self.gameStart = False
                      self.displayBoard()
                      if self.gameStatus == 'lose':
                          self.statusLabel = LabelNode('LOSE!', ('Anantason', 25), position = (self.size.x / 2, 750), scale = 3, color = '#ff0000')
                      if self.gameStatus == 'win':
                          self.statusLabel = LabelNode('WIN!', ('Anantason', 25), position = (self.size.x / 2, 750), scale = 3, color = '#7aff13')
                      self.add_child(self.statusLabel)
              #reset the touch inout
              self.x, self.y = 0, 0
          
      def countMines(board, coor):
          tileX, tileY = coor
          mineCount = 0
          #check surrounding tiles
          for y in range(-1, 2):
              for x in range(-1, 2):
                  try:
                      #prevent of negative index
                      if int(tileX) + x != -1 and int(tileY) + y != -1:
                          if board[int(tileY) + y][int(tileX) + x] == "#":
                              mineCount += 1
                  except IndexError:
                      pass
          return str(mineCount)
                      
      def zeroScanning(board, coordinate):
          PosX, PosY = coordinate
          board[PosY][PosX] = countMines(board, (PosX, PosY))
          if countMines(board, (PosX, PosY)) == '0':
              for testX in range(-1, 2):
                  for testY in range(-1, 2):       
                      PosX1 = PosX + testX
                      PosY1 = PosY + testY
                      try:
                          if (PosX1 != -1 and PosY1 != -1):
                              if countMines(board, (PosX1, PosY1)) == "0" and board[PosY1][PosX1] != '0':
                                  zeroScanning(board, (PosX1, PosY1))
                              else:
                                  board[PosY1][PosX1] = countMines(board, (PosX1, PosY1))
                      except IndexError:
                          pass
          return board
              
      if __name__ == '__main__':
          run(App(), LANDSCAPE) ```
      posted in Pythonista
      Tonnoaw
      Tonnoaw

    Latest posts made by Tonnoaw

    • RE: Try out my space shooter game, And I want your suggestions!

      Here is the updated one. I tried to make this game work on every screen sizes and add menu interface.
      https://github.com/Tonnoaw/game

      posted in Pythonista
      Tonnoaw
      Tonnoaw
    • RE: Try out my space shooter game, And I want your suggestions!

      @mikael Can you recommend me what is the next game should I do? For me to practice coding.

      posted in Pythonista
      Tonnoaw
      Tonnoaw
    • RE: Try out my space shooter game, And I want your suggestions!

      @mikael Thanks for your suggestions, In my next projects I will try experiment how to get all of my game working properly on all of screen sizes!

      posted in Pythonista
      Tonnoaw
      Tonnoaw
    • RE: How to create effect

      Thanks guys, I will study about shader and effect more Thanks!

      posted in Pythonista
      Tonnoaw
      Tonnoaw
    • Try out my space shooter game, And I want your suggestions!

      I created 2D space shooting game
      I want your suggestion from any experts or anyone. I have just learned Python for a month and I want some suggestions to improve my coding skills.
      I test and run this script on iPad

      from scene import *
      import sound
      import random
      import math
      A = Action
      
      class Laser(SpriteNode):
          def __init__(self, txture, object, **kwargs):
              SpriteNode.__init__(self, txture, **kwargs)
              self.shooter = object
      
      class Heart(SpriteNode):
          def __init__(self, **kwargs):
              SpriteNode.__init__(self, 'plf:HudHeart_full', **kwargs)
      
      class Enemy(SpriteNode):
          def __init__(self, txture, **kwargs):
              SpriteNode.__init__(self, txture, **kwargs)
              self.time = 0
              allow_move = random.choice(('x', 'y'))
              self.allow_move = allow_move
              
      class MyScene (Scene):
          def setup(self):
              self.move = 'up'; self.player_score = 0; self.touch_id_location = {}; self.touched = False;
              self.laser_on_screen = []; self.enemy_on_screen = []; self.player_health = 100; self.game_playing = True
              self.heart_on_screen = []; self.shown = False
              for x in range(int((self.size.x / 128)) + 1):
                  for y in range(int((self.size.y / 128)) + 1):
                      bg = SpriteNode(Texture('spc:BackgroundBlue'), position = (x * 128, y *128)); self.add_child(bg)
              self.score = LabelNode(f'Score: {self.player_score}', ('<System-Bold>', 30), position = (120, self.size.h - 30)); self.add_child(self.score)
              self.player_health_label = LabelNode(f'Health: {self.player_health}', ('<System-Bold>', 30), position = (self.size.w - 120, self.size.h - 30)); self.add_child(self.player_health_label)
              self.player = SpriteNode(Texture('spc:PlayerShip1Green'), position = (self.size.w / 2, self.size.h / 2))
              self.add_child(self.player)
              self.joy_layout = SpriteNode(Texture('iow:ios7_circle_outline_256'), position = (160, 160), alpha = 0.25, scale = 1)
              self.add_child(self.joy_layout)
              self.shoot_button = SpriteNode(Texture('iow:ios7_circle_filled_256'), position = (self.size.w - 160, 160), scale = 0.5, alpha = 0.25); self.add_child(self.shoot_button)
          
          def update(self):
              if self.game_playing:
                  if self.touched:
                      touch_location = self.touch_id_location.get(self.touch_in_joy)
                      self.move_ship()
                  if len(self.laser_on_screen) > 0:
                      for laser in self.laser_on_screen:
                          if laser.position.x > self.size.w or laser.position.y > self.size.h or laser.position.x < 0 or laser.position.y < 0 :
                              self.laser_on_screen.remove(laser)
                              laser.remove_from_parent()
                  self.spawn_enemy()
                  self.check_laser_collision()
                  self.score.text = f'Score: {self.player_score}'
                  self.player_health_label.text = f'Health: {self.player_health}'
                  self.move_enemy()
                  self.spawn_heart_pack()
                  self.check_player_get_heart()
              if self.player_health <= 0:
                  self.game_playing = False
                  self.joy_layout.remove_from_parent()
                  self.shoot_button.remove_from_parent()
                  for enemy in self.enemy_on_screen:
                      enemy.remove_from_parent()
                  for laser in self.laser_on_screen:
                      laser.remove_from_parent()
                  for heart in self.heart_on_screen:
                      heart.remove_from_parent()
                  self.player.remove_from_parent()
                  if not self.shown:
                      self.lose_scene()
                      self.shown = True
          
          def lose_scene(self):
              sound.play_effect('arcade:Explosion_4')
              self.lose_label = LabelNode('LOSE!', ('<System-Bold>', 60), position = (self.size.w /2, self.size.h / 2)); self.add_child(self.lose_label)
              self.score_label = LabelNode(f'Score: {self.player_score}', ('<System-Bold>', 50), position = (self.size.w /2, self.size.h / 2 - 100)); self.add_child(self.score_label)
                  
          
          def check_player_get_heart(self):
              for heart in self.heart_on_screen:
                  if self.player.position in heart.frame:
                      self.heart_on_screen.remove(heart)
                      heart.remove_from_parent()
                      sound.play_effect('arcade:Powerup_1')
                      self.player_health += 15
                              
          def touch_began(self, touch):
              self.touch_id_location[touch.touch_id] = touch.location
              if touch.location in self.joy_layout.frame and not self.touched:
                  self.joy_layout.run_action(A.sequence(A.scale_to(1.25, 0.025)))
                  self.joy_layout.position = touch.location
                  self.touch_in_joy = touch.touch_id
                  self.joy = SpriteNode(Texture('iow:ios7_circle_filled_256'), position = touch.location, alpha = 0.25, scale = 0.25)
                  self.add_child(self.joy)
                  self.test = SpriteNode(Texture('iow:ios7_circle_filled_256'), position = touch.location, scale = 0.25)
                  self.add_child(self.test)
                  self.touched = True
                  
              if touch.location in self.shoot_button.frame:
                  sound.play_effect('digital:Laser2')
                  self.shoot_button.run_action(A.sequence(A.scale_to(0.4, 0.05), A.scale_to(0.5, 0.05)))
                  self.shoot_laser(self.player.position, 'spc:LaserBlue9', self.player, self.move)
                  
                  
          def touch_moved(self, touch):
              self.touch_id_location[touch.touch_id] = touch.location
              try:
                  if touch.touch_id == self.touch_in_joy:
                      self.joy.position = touch.location
              except AttributeError:
                  pass
                  
          def touch_ended(self, touch):
              self.touch_id_location.pop(touch.touch_id)
              try:
                  if touch.touch_id == self.touch_in_joy:
                      self.joy.remove_from_parent()
                      self.joy_layout.run_action(A.sequence(A.scale_to(1, 0.025)))
                      self.joy_layout.position = (160, 160)
                      self.touched = False
                      self.test.remove_from_parent()
              except AttributeError:
                  pass
                  
          def move_ship(self):
              move_attributes = {
                  'up': ((0, 6), math.radians(0)),
                  'down': ((0, -6), math.radians(180)),
                  'left': ((-6, 0), math.radians(90)),
                  'right': ((6, 0), math.radians(270))
              }
              touch_position = self.touch_id_location.get(self.touch_in_joy)
              if touch_position not in self.test.frame:
                  if self.test.position.x - 64 < touch_position.x < self.test.position.x + 64:
                      if touch_position.y > self.test.position.y:
                          self.move = 'up'
                      else:
                          self.move = 'down'
                  if self.test.position.y - 64 < touch_position.y < self.test.position.y + 64:
                      if touch_position.x > self.test.position.x:
                          self.move = 'right'
                      else:
                          self.move = 'left'
                          
              m = move_attributes.get(self.move)
              try:
                  x = max(0, min(self.size.w, self.player.position.x + m[0][0]))
                  y = max(0, min(self.size.y, self.player.position.y + m[0][1]))
                  self.player.position = (x, y)
                  self.player.run_action(A.sequence(A.rotate_to(m[1], 0.025)))
              except TypeError:
                  pass
          
          def shoot_laser(self, position, txture, object, orient):
              if object == self.player:
                  laser_attributes = {
                      'up': ((0, 500), math.radians(0), (0, 64)),
                      'down': ((0, -500), math.radians(180), (0, -64)),
                      'left': ((-500, 0), math.radians(90), (-64, 0)),
                      'right': ((500, 0), math.radians(270), (64, 0))
                  }
              else:
                  laser_attributes = {
                      'up': ((0, 250), math.radians(0), (0, 64)),
                      'down': ((0, -250), math.radians(180), (0, -64)),
                      'left': ((-250, 0), math.radians(90), (-64, 0)),
                      'right': ((250, 0), math.radians(270), (64, 0))
                      }
              l = laser_attributes.get(orient)
              x, y = l[0]
              laser = Laser(txture, object); laser.position = (object.position.x + l[2][0], object.position.y + l[2][1])
              self.laser_on_screen.append(laser); self.add_child(laser)
              laser.run_action(A.sequence(A.rotate_to(l[1], 0.00001), A.repeat_forever(A.move_by(x, y))))
          
          def spawn_enemy(self):
              self.difficulty = 0.008 + self.player_score * 0.0000002
              if random.random() < self.difficulty and len(self.enemy_on_screen) <= 8:
                  index = random.choice([1, 0])
                  coor = [(random.uniform(200, self.size.w), random.uniform(self.size.h - 200, self.size.h)), (random.uniform(200, self.size.w - 200), random.uniform(0 ,200))]
                  x, y = coor[index]
                  txture = random.choice(['spc:EnemyGreen4', 'spc:EnemyBlack4', 'spc:EnemyBlue4'])
                  enemy = Enemy(txture)
                  if index == 0:
                       enemy.position = (self.size.w / 2, self.size.h + 48)
                  else:
                      enemy.position = (self.size.w / 2, -48)
                  enemy.run_action(A.sequence(A.move_to(x, y, 1)))
                  self.add_child(enemy) 
                  self.enemy_on_screen.append(enemy)
          
          def spawn_heart_pack(self):
              difficulty = self.difficulty * 0.05
              if random.random() < difficulty:
                  posX, posY =  (random.uniform(self.size.w - 300, 300), random.uniform(self.size.h - 300, 300))
                  self.heart = Heart(); self.heart.position = (posX, posY); self.heart.scale = 0.8
                  self.add_child(self.heart); self.heart_on_screen.append(self.heart)
                 
          def check_laser_collision(self):
              for laser in self.laser_on_screen:
                  for enemy in self.enemy_on_screen:
                      if laser.position in enemy.frame:
                          self.enemy_on_screen.remove(enemy)
                          enemy.remove_from_parent()
                          try:
                              self.laser_on_screen.remove(laser)
                          except ValueError:
                              pass
                          laser.remove_from_parent()
                          self.player_score += 80
                          sound.play_effect('arcade:Explosion_1')
                          self.explosion_effect(enemy.position)
                  if laser.position in self.player.frame and (laser.shooter in self.enemy_on_screen):
                      sound.play_effect('game:Error')
                      try:
                          self.laser_on_screen.remove(laser)
                      except ValueError:
                          pass
                          
                      self.player_health -= 5
                      laser.remove_from_parent()
                      for i in range(6):
                          particle = SpriteNode(Texture('spc:MeteorBrownMed2'), position = self.player.position, scale=random.uniform(0.3, 0.5))
                          actions1 = [A.group(A.move_by(random.uniform(-64, 64), random.uniform(-64, 64), random.uniform(0.4, 0.9)), A.rotate_by(random.uniform(1, 3), 0.4)), A.wait(0.4), A.fade_to(0, 0.3)] 
                          self.add_child(particle); particle.run_action(A.sequence(actions1))
                          
                         
          def explosion_effect(self, position):
              index = 0
              time = [0.0, 0.1, 0.2, 0.3, 0.4]
              for i in range(4):
                  explosion_texture = random.choice(('shp:Explosion01', 'shp:Explosion04', 'shp:Explosion00'))
                  ex_position = (position.x + random.uniform(-24, 24), position.y + random.uniform(-24, 24))
                  pa_position = (position.x + random.uniform(-16, 16), position.y + random.uniform(-16, 16))
                  actions = [A.wait(time[index]), A.fade_to(1, 0.04), A.wait(0.06), A.remove()]
                  exploded = SpriteNode(Texture(explosion_texture), position = ex_position, scale = random.uniform(0.25, 0.5), alpha = 0)
                  self.add_child(exploded); exploded.run_action(A.sequence(actions))
                  index += 1
                  particle = SpriteNode(Texture('spc:MeteorBrownMed2'), position = pa_position, scale=random.uniform(0.5, 0.8))
                  actions1 = [A.group(A.move_by(random.uniform(-64, 64), random.uniform(-64, 64), random.uniform(0.4, 0.9)), A.rotate_by(random.uniform(1, 3), 0.4)), A.wait(0.4), A.fade_to(0, 0.3)] 
                  self.add_child(particle); particle.run_action(A.sequence(actions1))
      
          def move_enemy(self):
              orient = ''
              for enemy in self.enemy_on_screen:
                  if not self.can_shoot_laser(enemy):      
                      if enemy.position.y > self.player.position.y and enemy.allow_move == "y":
                          orient = 'down'
                          self.enemy_moving(orient, enemy)
                      elif enemy.allow_move == 'y':
                          orient = 'up'
                          self.enemy_moving(orient, enemy)
                      if enemy.position.x > self.player.position.x and enemy.allow_move == "x":
                          orient = 'left'
                          self.enemy_moving(orient, enemy)
                      elif enemy.allow_move == 'x':
                          orient = 'right'
                          self.enemy_moving(orient, enemy)
                          
                  
          def enemy_moving(self, orient, enemy):
              move_attributes = {
                  'up': ((0, 2.5), math.radians(0)),
                  'down': ((0, -2.5), math.radians(180)),
                  'left': ((-2.5, 0), math.radians(90)),
                  'right': ((2.5, 0), math.radians(270))
              }
              try:
                  m = move_attributes.get(orient)
                  x = max(0, min(self.size.w, enemy.position.x + m[0][0]))
                  y = max(0, min(self.size.y, enemy.position.y + m[0][1]))
                  enemy.position = (x, y)
                  enemy.run_action(A.sequence(A.rotate_to(m[1], 0.025)))
              except (TypeError):
                  pass
                       
          def can_shoot_laser(self, enemy):
              aligned = False
              if self.player.position.x - 64 < enemy.position.x < self.player.position.x + 64:
                  enemy.time += 1
                  aligned = True
                  if enemy.position.y > self.player.position.y:
                      orient = 'down'
                  else:
                      orient = 'up'
                      
              if self.player.position.y - 64 < enemy.position.y < self.player.position.y + 64:
                  enemy.time += 1
                  aligned = True
                  if enemy.position.x > self.player.position.x:
                      orient = 'left'
                  else:
                      orient = 'right'
          
              if enemy.time > 60:
                  enemy.time = 0
                  self.shoot_laser(enemy.position, 'spc:LaserRed9', enemy, orient)
                  sound.play_effect('arcade:Laser_5')
                  if enemy.allow_move == 'x':
                      enemy.allow_move = 'y'
                  else:
                      enemy.allow_move = 'x'
              return aligned
              
      if __name__ == '__main__':
          run(MyScene(), show_fps=False) ```
      posted in Pythonista
      Tonnoaw
      Tonnoaw
    • How to create effect

      Create effect in scene module?
      I created 2D shooting game. I want to add smoke effect trailing after the player.
      So how can I create smoke effect and fade out after some duration.

      from scene import *
      import sound
      import random
      import math
      A = Action
      
      class Button(SpriteNode):
          def __init__(self, txt, **kwargs):
              SpriteNode.__init__(self, txt, **kwargs)
      
      
      class Laser(SpriteNode):
          def __init__(self, **kwargs):
              SpriteNode.__init__(self, 'spc:LaserBlue9', **kwargs)
              
                  
      class Enemy(SpriteNode):
          def __init__(self, **kwargs):
              img = random.choice(['spc:EnemyBlack1', 'spc:EnemyBlue2', 'spc:EnemyGreen5'])
              SpriteNode.__init__(self, img, **kwargs)    
              
              
      class MyScene (Scene):
          def setup(self):
              x = get_screen_size()
              self.laser_on_screen = []; self.touched = ''; self.touch_id_locations = {}; self.ship_orient = 'up'
              self.enemy_list = []
              bg = Node(parent=self)
              for x in range(int(self.size.w/ 128) + 1):
                  for y in range(int(self.size.h / 128) + 1):
                      tile = SpriteNode(Texture('spc:BackgroundPurple'), position = (x * 128, y * 128)); bg.add_child(tile)
              self.player = SpriteNode(Texture('spc:PlayerShip1Blue'), position = (self.size.w / 2, self.size.h / 2))
              self.add_child(self.player)
              self.button_down = Button('iob:arrow_down_a_256', scale= 0.5);self.button_down.position = (180, 120); self.add_child(self.button_down)
              self.button_up = Button('iob:arrow_up_a_256', scale= 0.5);self.button_up.position = (180, 280); self.add_child(self.button_up)
              self.button_left = Button('iob:arrow_left_a_256', scale= 0.5);self.button_left.position = (100, 200); self.add_child(self.button_left)
              self.button_right = Button('iob:arrow_right_a_256', scale= 0.5);self.button_right.position = (260, 200); self.add_child(self.button_right)
              self.button_shoot = Button('iob:ios7_circle_filled_256', scale= 0.5);self.button_shoot.position = (self.size.w - 180, 200); self.add_child(self.button_shoot)
          def did_change_size(self):
              pass
          
          def update(self):
              speed = 5
              self.laser_position_orientation = {
                  'up': ((self.player.position.x, self.player.position.y + 32), 0, 2000, 0.0),
                  'down': ((self.player.position.x, self.player.position.y - 32), 0, -2000, 3.14159),
                  'right': ((self.player.position.x + 32, self.player.position.y), 2000, 0, 4.71239),
                  'left': ((self.player.position.x - 32, self.player.position.y), -2000, 0, 1.5708),
              }
              for location in self.touch_id_locations.values():
                  if location in self.button_up.frame:
                      self.ship_orient = 'up'
                      self.player.position = (self.player.position.x, self.player.position.y + speed)
                      self.player.rotation = 0.0
                  if location in self.button_down.frame:
                      self.ship_orient = 'down'
                      self.player.position = (self.player.position.x, self.player.position.y - speed)
                      self.player.rotation = 3.14159
                  if location in self.button_left.frame:
                      self.ship_orient = 'left'
                      self.player.position = (self.player.position.x - speed, self.player.position.y)
                      self.player.rotation = 1.5708
                  if location in self.button_right.frame:
                      self.ship_orient = 'right'
                      self.player.position = (self.player.position.x + speed, self.player.position.y)
                      self.player.rotation = 4.71239
              for laser in self.laser_on_screen:
                  if laser.position.x > self.size.w or laser.position.x < 0 or laser.position.y > self.size.h or laser.position.y < 0:
                      laser.remove_from_parent()
                      self.laser_on_screen.remove(laser)
              if random.random() < 0.0055:
                  self.spawn_enemy()
              self.check_laser_collision()
          
                      
          def touch_began(self, touch):
              self.touch_id_locations[touch.touch_id] = touch.location
              if touch.location in self.button_shoot.frame:
                  laser_data_pack = self.laser_position_orientation.get(self.ship_orient)
                  sound.play_effect('digital:Laser1')
                  self.touch_id_locations.pop(touch.touch_id)
                  self.laser = Laser()
                  self.laser.position = laser_data_pack[0]; self.add_child(self.laser); self.laser.rotation = laser_data_pack[3]
                  self.laser_on_screen.append(self.laser)
                  self.laser.run_action(Action.sequence(Action.move_by(laser_data_pack[1], laser_data_pack[2])))
                  
          def touch_moved(self, touch):
              pass
              
          def touch_ended(self, touch):
              try:
                  self.touch_id_locations.pop(touch.touch_id)
              except KeyError:
                  pass
                  
          def get_key(self, val): 
              for key, value in self.touch_id_locations.items(): 
                   if val == value: 
                       return key 
              
          def spawn_enemy(self):
              enemy_position = (random.randint(0, self.size.w - 1), random.randint(0, self.size.h))
              self.enemy = Enemy(); self.enemy.position = enemy_position; self.add_child(self.enemy)
              self.enemy_list.append(self.enemy)
          
          def check_laser_collision(self):
              for laser in self.laser_on_screen:
                  for enemy in self.enemy_list:
                      if laser.position in enemy.frame:
                          enemy.remove_from_parent()
                          laser.remove_from_parent()
                          self.enemy_list.remove(enemy)
                          try:
                              self.laser_on_screen.remove(laser)
                          except ValueError:
                              pass
                          sound.play_effect('arcade:Explosion_2')
                          
      
      if __name__ == '__main__':
          run(MyScene(),DEFAULT_ORIENTATION,show_fps=False, multi_touch = True) ```
      posted in Pythonista
      Tonnoaw
      Tonnoaw
    • RE: I created 2D minesweeper game, Try out!

      @mikael Thanks for your suggestions . I'll apply your suggestions in my next projects and practices

      posted in Pythonista
      Tonnoaw
      Tonnoaw
    • I created 2D minesweeper game, Try out!

      I created 2D minesweeper game
      I've learned Python for a month and I decided to create 2D minesweeper game using scene module in Pythonista. I want some recommendations from any experts to make my code more cleaner and remove some unnecessary steps.
      Also try out my game :)

      from scene import *
      import sound
      import random
      
      #randomly install the mines on the board
      def setTheMine(board):
              for i in range(int(len(board))):
                  board[random.randint(0,len(board) - 1)][random.randint(0,len(board) - 1)] = "#"
              return board
              
      class App(Scene):    
          def setup(self):
              self.x, self.y = 0, 0
              #turn cheat to True to see the mines while playing
              self.cheat = False
              #create 2d matrix board
              # '-' = empty space and '#' = mine
              self.board = [["-" for i in range(10)] for i in range(10)]
              self.background_color = '#828adb'
              #install the mine
              self.board = setTheMine(self.board)
              #assign tile coordinates  
              self.tileDict = {}
              for row in range(len(self.board)):
                  for block in range(len(self.board[0])):
                      posist = str(block)+str(row)
                      posX_value = int(self.size.w / 2) - int((len(self.board) * 48) / 2) + (48 * block)
                      posY_value = int(self.size.h / 2) + int((len(self.board) * 48) / 2) - (48 * row)
                      x = self.tileDict.setdefault(posist, (posX_value, posY_value))
              #tile color according values
              self.tileColor = {
                  "0": 'pzl:Green3',
                  "1": 'pzl:Blue3',
                  "2": 'pzl:Yellow3',
                  "3": 'pzl:Red3',
                  "4": 'pzl:Red3',
                  "5": 'pzl:Red3',
                  "6": 'pzl:Red3',
                  "7": 'pzl:Red3',
                  "-": 'pzl:Gray3',
                  "#": 'pzl:Gray3'
              }
              self.labelFont = ('Adidas Unity', 50)
              self.gameStart = True
              #display 2D graphic board
              self.displayBoard()
              
          def touch_began(self, touch):
              self.x, self.y = touch.location
              
          def displayBoard(self):
              grid = Node(parent=self)
              row1 = 0
              for row in self.board:
                  column = 0
                  for block in row:
                      posX , posY = self.tileDict.get(str(column)+str(row1))
                      tile = SpriteNode(Texture(self.tileColor.get(block)), position = (posX, posY), scale = 1.5)
                      grid.add_child(tile)
                      if self.cheat:
                          if block == '#':
                              self.mine = SpriteNode(Texture('emj:Bomb'), position = (posX, posY), scale = 0.5)
                              self.add_child(self.mine)
                      if block is not "-" and block is not "#":
                          self.mineLabel = LabelNode(self.board[row1][column], self.labelFont, position = (posX, posY), scale = 0.5)
                          self.add_child(self.mineLabel)
                      column += 1
                  row1 += 1
                               
          def update(self):
              #check for touch input. is touch input on the board 
              found = False
              for y in range(len(self.board)):
                  for x in range(len(self.board[0])):
                      testCase = str(x)+str(y)
                      #x and y coordinates for each tile
                      testPosX, testPosY = self.tileDict.get(testCase)
                      if testPosX - 24 < self.x < testPosX + 24 and testPosY - 24 < self.y < testPosY + 24: 
                          self.x, self.y = 0, 0
                          sound.play_effect('8ve:8ve-beep-shinymetal')
                          if self.gameStart:
                              found = True
                          #tile that user touched
                          tileSelected = testCase
                          break
                  if found:
                      break
              if found:
                  #check if user touched on the mine
                  if self.board[int(tileSelected[1])][int(tileSelected[0])] is "#":
                      self.gameStart = False
                      self.gameStatus = 'lose'
                  else:
                  #else reveal the number of mines that surround the tile
                      if self.board[int(tileSelected[1])][int(tileSelected[0])] is not "#":
                          self.board = zeroScanning(self.board, (int(tileSelected[0]), int(tileSelected[1])))
                  self.foundSpace = False
                  #check if all tiles are revealed
                  for row in self.board:
                      for tile in row:
                          if tile is '-':
                              self.foundSpace = True
                              break
                      if self.foundSpace:
                          break
                  #if there is no empty tile left = win!
                  if self.foundSpace == False:
                      self.gameStatus = 'win'
                      self.gameStart = False
                  if self.gameStart:
                      self.displayBoard()
                  #if game ends
                  else:
                      #reveals the mine
                      self.cheat = True
                      self.gameStart = False
                      self.displayBoard()
                      if self.gameStatus == 'lose':
                          self.statusLabel = LabelNode('LOSE!', ('Anantason', 25), position = (self.size.x / 2, 750), scale = 3, color = '#ff0000')
                      if self.gameStatus == 'win':
                          self.statusLabel = LabelNode('WIN!', ('Anantason', 25), position = (self.size.x / 2, 750), scale = 3, color = '#7aff13')
                      self.add_child(self.statusLabel)
              #reset the touch inout
              self.x, self.y = 0, 0
          
      def countMines(board, coor):
          tileX, tileY = coor
          mineCount = 0
          #check surrounding tiles
          for y in range(-1, 2):
              for x in range(-1, 2):
                  try:
                      #prevent of negative index
                      if int(tileX) + x != -1 and int(tileY) + y != -1:
                          if board[int(tileY) + y][int(tileX) + x] == "#":
                              mineCount += 1
                  except IndexError:
                      pass
          return str(mineCount)
                      
      def zeroScanning(board, coordinate):
          PosX, PosY = coordinate
          board[PosY][PosX] = countMines(board, (PosX, PosY))
          if countMines(board, (PosX, PosY)) == '0':
              for testX in range(-1, 2):
                  for testY in range(-1, 2):       
                      PosX1 = PosX + testX
                      PosY1 = PosY + testY
                      try:
                          if (PosX1 != -1 and PosY1 != -1):
                              if countMines(board, (PosX1, PosY1)) == "0" and board[PosY1][PosX1] != '0':
                                  zeroScanning(board, (PosX1, PosY1))
                              else:
                                  board[PosY1][PosX1] = countMines(board, (PosX1, PosY1))
                      except IndexError:
                          pass
          return board
              
      if __name__ == '__main__':
          run(App(), LANDSCAPE) ```
      posted in Pythonista
      Tonnoaw
      Tonnoaw