メインコンテンツへスキップ
見出し画像

【pyxel 1.5】pyxelで3D迷路を作ってみる(2)

    前回は3D迷路を作り、歩き回れるところまで進めてみました。迷路データは10*10でリストの形で持たせていました。今回は迷路データをPyxel Editorで作成したタイルマップから取り込み、より大きな迷路を作ってみたいと思います。

    画像

    ▲見た目にはあまり変化がないですが、迷路が大きくなりました。プレイヤーの位置を示すコンパス部分にも手を加えています。

    ここまでの進行具合は以下のnoteをご参照ください。

    まずはPyxel Editorで迷路のタイルマップを作ります。

    画像

    ▲とりあえずはシンプルに。白が通路で、灰が壁です。pyxel1.5.0以降はタイルマップをコードで使う際の指定の仕方が変わり、タプル形式になっています。例えば白マスは(0, 0)で灰マスは(1, 0)です。「何行目の何個目のタイル」って感じですね。以前は0から連番で振られていたので、わかりやすくなりました。

    これを4枚作ってつなげます。

    画像

    ▲雑ですが今回作った迷路の全体像はこんな感じ。これを取り込んでみます。

    それではコード部分に入っていきます。

      def __init__(self):
          pyxel.init(256, 256, title = "pyxel")
          pyxel.load('assets/assets.pyxres')
          
          self.data = []
          self.maze = []
           
          #Maze set
          for i in range(32):
              self.data = []
              for i2 in range(32):
                  self.data.append(pyxel.tilemap(0).pget(i2,i))
              self.maze.append(self.data)
          
          #Player position
          self.pos = [1, 1]
          
          #Angle P=Player
          #    ^
          #    1
          #<4  P   2>
          #    3
          #    v
          #     
          self.pos_angle = 3
          
          self.wall = [[0, 0],
                       [0, 0],
                       [0, 0],
                       [0, 0],]
          #Wall set
          for i1 in range(5):
              x1 = self.pos[1] - (1 * i1)
              if self.maze[x1][self.pos[0]] == 1:
                  self.dead_end = i1      
          self.dead_end = 0
          
          pyxel.run(self.update, self.draw)

    ▲init部分が大きく変わりました。まず.pyxresファイルを使うようになったので、pyxel.loadで読み込んでいます。その後、迷路データを読み込むための配列dataと最終的に迷路データを格納する配列mazeを宣言。今回は縦横32のサイズなので、「for i in range(32):」でループ文をまわしながら迷路を格納していきます。横1行分をdataに入れたら、それをmazeに追加して次の行に進むことの繰り返しです。
    そのほかはコメント行を追加しましたが特に変わりありません。

      def update(self): 
          
          #Wall reset
          self.wall = [[0, 0],
                       [0, 0],
                       [0, 0],
                       [0, 0],]      
                  
          #Go ahead
          if pyxel.btnp(pyxel.KEY_UP):
              self.dead_end = 0
              if self.pos_angle == 1:
                  if self.maze[self.pos[1] - 1][self.pos[0]] == (0, 0):
                      self.pos[1] = self.pos[1] - 1
                      self.pos_angle = 1
              elif self.pos_angle == 2:
                  if self.maze[self.pos[1]][self.pos[0] + 1] == (0, 0):
                      self.pos[0] = self.pos[0] + 1
                      self.pos_angle = 2
              elif self.pos_angle == 3:
                  if self.maze[self.pos[1] + 1][self.pos[0]] == (0, 0):
                      self.pos[1] = self.pos[1] + 1
                      self.pos_angle = 3
              elif self.pos_angle == 4:
                  if self.maze[self.pos[1]][self.pos[0] - 1] == (0, 0):
                      self.pos[0] = self.pos[0] - 1     
                      self.pos_angle = 4
                      
    
          #Turn to the back
          if pyxel.btnp(pyxel.KEY_DOWN):
              self.dead_end = 0
              if self.pos_angle == 1:
                  self.pos_angle = 3
              elif self.pos_angle == 2:
                  self.pos_angle = 4
              elif self.pos_angle == 3:
                  self.pos_angle = 1
              elif self.pos_angle == 4:
                  self.pos_angle = 2
              
          #Turn to the right
          if pyxel.btnp(pyxel.KEY_RIGHT):
              self.dead_end = 0
              if self.pos_angle == 1:
                  self.pos_angle = 2
              elif self.pos_angle == 2:              
                  self.pos_angle = 3
              elif self.pos_angle == 3:              
                  self.pos_angle = 4
              elif self.pos_angle == 4:              
                  self.pos_angle = 1
              
          #Turn to the left
          if pyxel.btnp(pyxel.KEY_LEFT):
              self.dead_end = 0
              if self.pos_angle == 1:
                  self.pos_angle = 4
              elif self.pos_angle == 2:             
                  self.pos_angle = 1
              elif self.pos_angle == 3:              
                  self.pos_angle = 2
              elif self.pos_angle == 4:
                  self.pos_angle = 3    
      
          #Wall set///////////////////////////////////////////////////////////////        
          if self.pos_angle == 1:
              for i1 in range(4):
                  if self.pos[1] - i1 < 0:
                      break
                  for i2 in range(2):
                      p1 = self.pos[1] - (1 * i1)
                      p2 = self.pos[0] - 1 + (2 * i2) 
                  
                      self.wall[i1][i2] = self.maze[p1][p2]
                  
                      if self.maze[p1][self.pos[0]] == (1, 0):
                          if self.dead_end == 0:
                              self.dead_end = i1
                          if self.dead_end > i1:
                              self.dead_end = i1
                          
          elif self.pos_angle == 3:
              for i1 in range(4):
                  if self.pos[1] + i1 > 31:
                      break
                  for i2 in range(2):
                      p1 = self.pos[1] + (1 * i1)
                      p2 = self.pos[0] + 1 - (2 * i2) 
                  
                      self.wall[i1][i2] = self.maze[p1][p2]
                  
                      if self.maze[p1][self.pos[0]] == (1, 0):
                          if self.dead_end == 0:
                              self.dead_end = i1
                          if self.dead_end > i1:
                              self.dead_end = i1
                          
          elif self.pos_angle == 2:
              for i1 in range(4):
                  if self.pos[0] + i1 > 31:
                      break
                  for i2 in range(2):
                      p1 = self.pos[1] - 1 + (2 * i2) 
                      p2 = self.pos[0] + (1 * i1)
                  
                      self.wall[i1][i2] = self.maze[p1][p2]
                  
                      if self.maze[self.pos[1]][p2] == (1, 0):
                          if self.dead_end == 0:
                              self.dead_end = i1
                          if self.dead_end > i1:
                              self.dead_end = i1             
                              
          elif self.pos_angle == 4:
              for i1 in range(4):
                  if self.pos[0] - i1 < 0:
                      break
                  for i2 in range(2):
                      p1 = self.pos[1] + 1 - (2 * i2) 
                      p2 = self.pos[0] - (1 * i1)
                  
                      self.wall[i1][i2] = self.maze[p1][p2]
                  
                      if self.maze[self.pos[1]][p2] == (1, 0):
                          if self.dead_end == 0:
                              self.dead_end = i1
                          if self.dead_end > i1:
                              self.dead_end = i1            
          #///////////////////////////////////////////////////////////////////////

    ▲update部分です。変更点としては壁の有無を検査する際の上限値を迷路のサイズに合わせて変更しました。この辺りは将来的には変数にすると拡張性があるかもしれないですね。また、プレイヤー移動先が通路なのか壁なのかを判定する部分を、タイルマップから引いてきた迷路データに合わせて修正しました。タイルマップのタイル種類はタプルとして持たれているので、「if self.maze[self.pos[1] - 1][self.pos[0]] == (0, 0):」のような形で比較します。(0, 0)は通路マスです。

      def draw(self):
          pyxel.cls(0)
          
          pyxel.rectb(0, 150, 256, 106, 1)
          
    #Draw wall 1------------------------------------------------------------------      
          if self.wall[0][0] == (1, 0):
              pyxel.line(0, 0, 50, 29, 6)
              pyxel.line(0, 0, 0, 150, 6)
              pyxel.line(0, 150, 50, 121, 6)
              pyxel.line(50, 29, 50, 121, 6)
          else:
              pyxel.line(0, 29, 50, 29, 6)
              pyxel.line(0, 121, 50, 121, 6)
          if self.wall[0][1] == (1, 0):       
              pyxel.line(256, 0, 205, 29, 6)
              pyxel.line(256, 150, 205, 121, 6)      
              pyxel.line(255, 0, 255, 150, 6)
              pyxel.line(205, 29, 205, 121, 6)
          else:
              pyxel.line(256, 29, 205, 29, 6)
              pyxel.line(256, 121, 205, 121, 6)
    #-----------------------------------------------------------------------------          
    
    #Draw wall 2------------------------------------------------------------------                    
          if self.wall[1][0] == (1, 0):       
              pyxel.line(50, 29, 80, 45, 12)
              pyxel.line(50, 121, 80, 105, 12)
              pyxel.line(50, 29, 50, 121, 12)
              pyxel.line(80, 45, 80, 105, 12)
          else:          
              pyxel.line(79, 45, 51, 45, 12)
              pyxel.line(79, 105, 51, 105, 12)
          if self.wall[1][1] == (1, 0):       
             pyxel.line(205, 29, 175, 45, 12)
             pyxel.line(205, 121, 175, 105, 12)
             pyxel.line(205, 29, 205, 121, 12)
             pyxel.line(175, 45, 175, 105, 12)
          else:          
              pyxel.line(176, 45, 204, 45, 12)
              pyxel.line(176, 105, 204, 105, 12)      
    #----------------------------------------------------------------------------          
          
    #Draw wall 3-----------------------------------------------------------------                  
          if self.wall[2][0] == (1, 0):       
              pyxel.line(80, 45, 97, 55, 5)
              pyxel.line(80, 105, 97, 95, 5)
              pyxel.line(80, 45, 80, 105, 5)
              pyxel.line(97, 55, 97, 95, 5)
          else:
              pyxel.line(97, 55, 81, 55, 5)
              pyxel.line(97, 95, 81, 95, 5)
          if self.wall[2][1] == (1, 0):       
              pyxel.line(175, 45, 158, 55, 5)
              pyxel.line(175, 105, 158, 95, 5)
              pyxel.line(175, 45, 175, 105, 5)
              pyxel.line(158, 55, 158, 95, 5)
          else:
              pyxel.line(158, 55, 174, 55, 5)
              pyxel.line(158, 95, 174, 95, 5)
    #----------------------------------------------------------------------------
    
    #Draw wall 4-----------------------------------------------------------------                  
          if self.wall[3][0] == (1, 0):       
              pyxel.line(97, 55, 108, 60, 1)
              pyxel.line(97, 95, 108, 90, 1)
              pyxel.line(97, 55, 97, 95, 1)
              pyxel.line(108, 60, 108, 90, 1)    
          if self.wall[3][1] == (1, 0):       
             pyxel.line(158, 55, 148, 60, 1)
             pyxel.line(158, 95, 148, 90, 1)  
             pyxel.line(158, 55, 158, 95, 1)
             pyxel.line(148, 60, 148, 90, 1)      
    #-----------------------------------------------------------------------------      
        
    #Draw Dead-End----------------------------------------------------------------
          if self.dead_end == 0:
              pass
          elif self.dead_end == 1:
              pyxel.rect(50, 29, 156, 93, 0)
              pyxel.rectb(50, 29, 156, 93, 6)
          elif self.dead_end == 2:
              pyxel.rect(80, 45, 96, 61, 0)
              pyxel.rectb(80, 45, 96, 61, 12)
          elif self.dead_end == 3:
              pyxel.rect(97, 55, 62, 41, 0)
              pyxel.rectb(97, 55, 62, 41, 5)
          elif self.dead_end == 4:
              pyxel.rect(108, 60, 41, 30, 0)
              pyxel.rectb(108, 60, 41, 30, 1)
    #-----------------------------------------------------------------------------          
              
    #Draw Compass-----------------------------------------------------------------
          pyxel.rectb(14, 164, 55, 45, 13)
          for d0 in range(5):
              if (self.pos[1]-1 < 0 or 
                  self.pos[0]-2+d0 < 0 or self.pos[0]-2+d0 > 31):
                  pass          
              elif self.maze[self.pos[1]-1][self.pos[0]-2+d0] == (1, 0):
                  pyxel.rect(17+10*d0, 167, 9, 9, 7)
          for d1 in range(5):
              if self.pos[0]-2+d1 < 0 or self.pos[0]-2+d1 > 31:
                  pass          
              elif self.maze[self.pos[1]][self.pos[0]-2+d1] == (1, 0):
                  pyxel.rect(17+10*d1, 177, 9, 9, 7)
          for d2 in range(5):
              if (self.pos[1]+1 > 31 or
                  self.pos[0]-2+d2 < 0 or self.pos[0]-2+d2 > 31):
                  pass          
              elif self.maze[self.pos[1]+1][self.pos[0]-2+d2] == (1, 0):
                  pyxel.rect(17+10*d2, 187, 9, 9, 7)
          for d3 in range(5):
              if (self.pos[1]+2 > 31 or
                  self.pos[0]-2+d3 < 0 or self.pos[0]-2+d3 > 31):
                  pass          
              elif self.maze[self.pos[1]+2][self.pos[0]-2+d3] == (1, 0):
                  pyxel.rect(17+10*d3, 197, 9, 9, 7)              
    
                
          if self.pos_angle == 1:
              pyxel.tri(41, 178, 37, 185, 45, 185, 8)
          elif self.pos_angle == 2:
              pyxel.tri(45, 181, 37, 178, 37, 185, 8)
          elif self.pos_angle == 3:
              pyxel.tri(41, 185, 37, 178, 45, 178, 8)
          elif self.pos_angle == 4:
              pyxel.tri(37, 183, 45, 178, 45, 186, 8)
    #-----------------------------------------------------------------------------    
          

    ▲draw部分です。ほとんど変わっていませんが、コンパスの描画範囲を広げ、壁を四角で表示するようにしました。

    画像

    ▲左が前回までのコンパス、右が今回修正したものです。描写範囲が広がり、壁の向こうの通路が少し見えます。

    まぁまぁ様になってきましたかね。今のところはただの迷路なので、もう少しゲーム的な要素を加えていきたいところです。

    コードやpyxresファイル、モジュールファイルはGitHubの方に置いてあります。

    今回はここまで。
    読んでいただきありがとうございました。


    この記事が参加している募集

     
     
    出版社のしがない社内SE。 ここでは主に趣味のプログラミングやゲーム制作について書いています。作ったゲームは https://koidemizu.github.io/ で公開しているのでよかったら遊んでください。 ゲーム大好きインドア派。

    あなたへのおすすめ