Pythonista3でインベーダーゲーム風を作った
インベーダー、自機ロケット、ミサイル、敵爆弾のpng ファイルが必要
インベーダーは2枚のキャラを1秒ごとに切り替える。またミサイルがぶつかったら赤くする
ーーーソースコード---
from scene import *
import threading
import random
from math import *
#import dialogs
import console
class InvaderSprite(SpriteNode):
def init(self, p):
super().init('INVADER.png')
self.position = p
self.size /= 8
self.img_no: int = 0
self.img = [
Texture('INVADER.png'),
Texture('INVADER_2.png'),
Texture('INVADER_3.png')]
def change_img(self):
self.texture = self.img[self.img_no]
self.size = self.img[self.img_no].size / 8
if self.img_no == 0:
self.img_no = 1
elif self.img_no == 1:
self.img_no = 0
elif self.img_no == 2:
pass
else:
pass
class RocketSprite(SpriteNode):
def init(self, p):
super().init('ROCKET.png') #('emj:Rocket')
self.position = p
self.size /= 9
class MonsterSprite(SpriteNode):
def init(self, p):
super().init('emj:Alien_Monster')
self.position = p
class MisileSprite(SpriteNode):
def init(self, p):
super().init('MISSILE.png') #('emj:Pushpin_1')
self.position = p
self.size /= 30 #3
class FireSprite(SpriteNode):
def init(self, p):
super().init('emj:Fire')
self.position = p
self.size /= 2
class AlienSprite(SpriteNode):
def init(self):
super().init('plf:AlienPink_front')
self.img = [['plf:AlienPink_front','plf:AlienPink_swim1','plf:AlienPink_swim2','plf:AlienPink_walk1','plf:AlienPink_walk2','plf:AlienPink_climb1', 'plf:AlienPink_climb2','plf:AlienPink_duck','plf:AlienPink_hit','plf:AlienPink_jump','plf:AlienPink_stand'],
['plf:AlienBlue_front','plf:AlienBlue_swim1','plf:AlienBlue_swim2','plf:AlienBlue_walk1','plf:AlienBlue_walk2','plf:AlienBlue_climb1', 'plf:AlienBlue_climb2','plf:AlienBlue_duck','plf:AlienBlue_hit','plf:AlienBlue_jump','plf:AlienBlue_stand'],
['plf:AlienGreen_front','plf:AlienGreen_swim1','plf:AlienGreen_swim2','plf:AlienGreen_walk1','plf:AlienGreen_walk2','plf:AlienGreen_climb1', 'plf:AlienGreen_climb2','plf:AlienGreen_duck','plf:AlienGreen_hit','plf:AlienGreen_jump','plf:AlienGreen_stand'],
['plf:AlienYellow_front','plf:AlienYellow_swim1','plf:AlienYellow_swim2','plf:AlienYellow_walk1','plf:AlienYellow_walk2','plf:AlienYellow_climb1', 'plf:AlienYellow_climb2','plf:AlienYellow_duck','plf:AlienYellow_hit','plf:AlienYellow_jump','plf:AlienYellow_stand'],
['plf:AlienBeige_front','plf:AlienBeige_swim1','plf:AlienBeige_swim2','plf:AlienBeige_walk1','plf:AlienBeige_walk2','plf:AlienBeige_climb1', 'plf:AlienBeige_climb2','plf:AlienBeige_duck','plf:AlienBeige_hit','plf:AlienBeige_jump','plf:AlienBeige_stand']
]
self.img_no: int = 0
def change_img(self, char_no, img_no):
self.texture = Texture(self.img[char_no][img_no])
class GameScene(Scene):
ALIEN_SP_CHAR_MAX = 5
ALIEN_SP_NO_MAX = 10
MONSTER_COUNT_MAX = 5
ROCKET_COUNT_MAX = 5
MONSTER_CREATE_COUNT_MAX = 3
MONSTER_ERASE_COUNT_MAX = 3
MONSTER_ERASE_POINT = 100
ROCKET_CREATE_COUNT_MAX = 3
ROCKET_ERASE_COUNT_MAX = 3
ALIEN_Y_ORG = 80
INVADER_ERASE_POINT = 20
INVADER_X_ADD = 10
INVADER_Y_ADD = 40
def setup(self):
#print("setup")
self.playing = False
self.char_no: int = 0
self.background_color = '#e0e0e0'
self.alien_sp = [[None,None,None,None,None,None,None,None,None,None],[None,None,None,None,None,None,None,None,None,None],
[None,None,None,None,None,None,None,None,None,None],
[None,None,None,None,None,None,None,None,None,None],
[None,None,None,None,None,None,None,None,None,None],
]
self.scene_w = self.size.w
self.scene_h = self.size.h
#self.rocket_sp = Node()
#self.monster_sp = Node()
#self.fire_sp = Node()
#self.alien_sp = Node()
self.monster_x_add = 10
self.monster_y_add = 40
self.alien_data = [[False,False,False,False,False,False,False,False,False,False],[False,False,False,False,False,False,False,False,False,False],[False,False,False,False,False,False,False,False,False,False],[False,False,False,False,False,False,False,False,False,False],[False,False,False,False,False,False,False,False,False,False],]
self.alien_count: int = self.ALIEN_SP_CHAR_MAX * self.ALIEN_SP_NO_MAX
self.monster_count: int = self.MONSTER_COUNT_MAX
self.rocket_count: int = self.ROCKET_COUNT_MAX
self.rocket_create_count: int = 0
self.monster_erase_point: int = 999999
self.rocket_erase_count: int = 0
self.createLabelNode()
self.createAlienSprite()
p = self.size
p.x = self.scene_w / 2
p.y = 30
self.createRocketSprite(p)
p = self.size
p.x = 0
p.y = self.scene_h - 40 #self.size.h / 2
self.createMonsterSprite(p)
self.createFireSprite()
self.createMisileSprite()
# invader
self.invader_erase_point = 999999
p = self.size
p.x = 0. #self.scene_w /2
p.y = self.scene_h /2 - 80
self.createInvaderSprite(p)
self.invader_sp.change_img()
threading.Timer(1.0, self.timerAlien).start()
self.playing = True
def update(self):
if self.playing == False:
return
# 位置移動
self.setMonsterPosition()
self.setMisilePosition()
self.setFirePosition()
# 衝突処理
self.checkCollisions()
# monster , alien カウント表示
self.label_node.text="[rocket=%d monster=%02d alien=%02d ]" % (self.rocket_count,self.monster_count,self.alien_count)
# 終了確認
if self.alien_count==0 and self.monster_count==0 :
self.label_node.text += "You Win!"
self.playing = False
if self.rocket_count==0:
self.label_node.text += "Game Over"
self.playing = False
return
def draw(self):
#print("draw")
ellipse(50, 0, 200, 200)
fill(0.75, 0.6, 1.0, 0.25)
rect(150, 100, 200, 200)
ellipse(550, 300, 300, 300)
fill(0.75,0.55,0.4,0.25)
rect(50, 350, 300, 300)
return
def touch_began(self, touch):
#print('touch_began()')
if self.playing == False:
return
p = touch.location
#self.label_node.text="[%04d,%04d]:began" % (p.x,p.y)
#self.label_node.text="[monster=%02d,alien=%02d]:began" % (self.monster_count,self.alien_count)
p.y = 30
act = Action.move_to(p.x, p.y, 1.0 , TIMING_LINEAR)
self.rocket_sp.run_action(act)
return
def touch_moved(self, touch):
p = touch.location
#self.label_node.text="[%04d,%04d]:moved" % (p.x,p.y)
#self.label_node.text="[monster=%02d,alien=%02d]:moved" % (self.monster_count,self.alien_count)
self.rocket_sp.position.x = p.x
return
def touch_ended(self, touch):
p = touch.location
#self.label_node.text="[%04d,%04d]:ended" % (p.x,p.y)
#self.label_node.text="[monster=%02d,alien=%02d]:ended" % (self.monster_count,self.alien_count)
return
def cuclPositionAlien(self, sp):
p = sp.position
p.x += 10 #X 移動距離
#右端まで行ったら改行する
if p.x >= self.scene_w: #self.size.w:
p.x = 0
p.y -= 40 #Y 移動距離
# 最下行まで行ったら1番上に戻る
if p.y <= 0:
p.y = self.scene_h #self.size.h
sp.position = p
# Timer
def timerAlien(self):
if self.playing == False:
return
#Invader
self.invader_sp.change_img()
self.setInvaderPosition()
#Alien位置移動とイメージ変更
for char in range(self.ALIEN_SP_CHAR_MAX):
for no in range(self.ALIEN_SP_NO_MAX):
self.cuclPositionAlien(self.alien_sp[char][no])
image_no = random.randint(0, self.ALIEN_SP_NO_MAX) #self.alien_sp[no].IMG_NO_MAX-1)
self.alien_sp[char][no].change_img(char, image_no)
#モンスタ位置移動
self.setMonsterPosition()
# ロケット消去
if self.rocket_erase_count == 1:
self.rocket_erase_count = 0
self.rocket_sp.remove_from_parent()
elif self.rocket_erase_count > 1:
self.rocket_erase_count -= 1
# ロケット出現処理
if self.rocket_create_count == 1:
#次のロケット出現
self.rocket_create_count = 0
self.createRocketSprite(self.rocket_sp.position)
self.createMisileSprite()
elif self.rocket_create_count > 1:
self.rocket_create_count -= 1
#else:
threading.Timer(1.0,self.timerAlien).start()
return
#
def createLabelNode(self):
self.label_node = LabelNode('[rocket=%d monster=%02d alien=%02d]' % (self.rocket_count,self.monster_count,self.alien_count))
self.label_node.font=('Helvetica',36)
self.label_node.color='black'
p = self.label_node.position
p.y = self.size.h - 26
p.x = self.size.w / 2
self.label_node.position = p
self.add_child(self.label_node)
#print("createLabelNode")
#
def createAlienSpriteSingle(self, char, no):
sp = AlienSprite()
self.alien_sp[char][no] = sp
p = self.alien_sp[char][no].position
p.x = 40 + (60 * no)
p.y = self.size.h - (self.ALIEN_Y_ORG + (80 * char))
self.alien_sp[char][no].position = p
self.add_child(self.alien_sp[char][no])
self.alien_sp[char][no].change_img(char, no)
#
def createAlienSprite(self):
#print("createAlienSprite")
for char in range(self.ALIEN_SP_CHAR_MAX):
for no in range(self.ALIEN_SP_NO_MAX):
self.createAlienSpriteSingle(char, no)
#
def createRocketSprite(self, p):
self.rocket_sp = RocketSprite(p)
self.add_child(self.rocket_sp)
#print("rocket_sp.position=%s" % self.rocket_sp.position)
#
def createMonsterSprite(self, p):
self.monster_sp = MonsterSprite(p)
self.add_child(self.monster_sp)
#print("monster_sp.position=%s" % self.monster_sp.position)
def createFireSprite(self):
p = self.monster_sp.position
p.x = self.monster_sp.position.x
p.y = self.monster_sp.position.y
self.fire_sp = FireSprite(p)
self.add_child(self.fire_sp)
#print("fire_sp.position=%s" % self.fire_sp.position)
def createMisileSprite(self):
p = self.rocket_sp.position
p.x = self.rocket_sp.position.x
p.y = self.rocket_sp.position.y + 60
#print(self.misile_sp)
self.misile_sp = MisileSprite(p)
self.add_child(self.misile_sp)
#print("misile_sp.position=%s" % self.misile_sp.position)
def createInvaderSprite(self, p):
self.invader_sp = InvaderSprite(p)
self.add_child(self.invader_sp)
# invader
def setInvaderPosition(self):
p = self.invader_sp.position
if p.x >= self.invader_erase_point:
#console.alert("invader erase point%d < %d" % (self.invader_erase_point ,p.x))
self.invader_sp.remove_from_parent()
self.invader_erase_point = 99999
p.x = 0
self.invader_sp.position = p
self.invader_sp.img_no = 0
self.createInvaderSprite(p)
p = self.invader_sp.position
if p.x > self.scene_w:
p.x = 0
p.y -= self.INVADER_Y_ADD
else:
p.x += self.INVADER_X_ADD
self.invader_sp.position = p
# monster位置セット
def setMonsterPosition(self):
# Monster
p = self.monster_sp.position
if p.x >= self.monster_erase_point:
self.monster_sp.remove_from_parent()
self.monster_erase_point = 99999
if self.monster_count > 0:
p.x = 0
p.y = self.scene_h - 40
self.createMonsterSprite(p)
if p.x >= self.scene_w: #self.size.w:
#右端にきたらモンスタを消す
self.monster_sp.remove_from_parent()
if self.monster_count > 0:
p.x = 0 #左端から再スタート
p.y -= self.monster_y_add #1行下
self.createMonsterSprite(p)
#self.createFireSprite()
else:
p = self.monster_sp.position
p.x += self.monster_x_add
self.monster_sp.position = p
if p.y <= self.monster_y_add:
p = self.monster_sp.position
p.y = self.scene_h - 40 #self.size.y / 2 - 40
self.misile_sp.position = p
# Fire位置セット
def setFirePosition(self):
p = self.fire_sp.position
if p.y <= 0:
self.fire_sp.remove_from_parent()
self.fire_sp.position = self.monster_sp.position
if self.monster_count > 0 :
self.createFireSprite()
else:
p.y -=5
self.fire_sp.position = p
# misile位置セット
def setMisilePosition(self):
p = self.misile_sp.position
if p.y >= self.scene_h: #self.size.h:
self.misile_sp.remove_from_parent()
if self.rocket_count > 0 and self.rocket_create_count == 0:
p = self.rocket_sp.position
self.createMisileSprite()
else:
p.y +=10
self.misile_sp.position = p
# 衝突処理
def checkCollisions(self):
# Monster vs Misile
if self.is_collided(self.monster_sp,self.misile_sp):
#print("monster vs misile [%s][%s]" % (self.monster_sp.position,self.misile_sp.position))
self.misile_sp.remove_from_parent()
self.misile_sp.position = self.rocket_sp.position
self.monster_sp.color = 'red'
self.monster_erase_point = self.monster_sp.position.x + self.MONSTER_ERASE_POINT
if self.monster_count > 0:
self.monster_count -= 1
# Alien vs Misile
for char in range(self.ALIEN_SP_CHAR_MAX):
for no in range(self.ALIEN_SP_NO_MAX):
if self.is_collided(self.alien_sp[char][no],self.misile_sp):
self.misile_sp.remove_from_parent()
self.misile_sp.position = self.rocket_sp.position
#self.alien_sp[char][no].color = 'red'
self.alien_sp[char][no].remove_from_parent()
self.alien_sp[char][no].position = self.size
if self.rocket_create_count == 0:
# 通常はミサイルを作成するが、ロケット作成待ちの間はミサイルを作成しない
self.createMisileSprite()
if self.alien_data[char][no]:
continue
else:
self.alien_data[char][no]=True
if self.alien_count > 0:
self.alien_count -= 1
# Rocket vs Fire
if self.rocket_create_count == 0 and self.monster_count > 0:
if self.is_collided(self.rocket_sp,self.fire_sp):
#print("rocket vs fire [%s][%s]" % (self.rocket_sp.position,self.fire_sp.position))
self.fire_sp.remove_from_parent()
#self.fire_sp.position = self.monster_sp.position
self.rocket_sp.color = 'red'
self.rocket_erase_count = self.ROCKET_ERASE_COUNT_MAX
#act = Action.fade_to(0.0, 1.0,TIMING_LINEAR)
#self.rocket_sp.run_action(act)
if self.rocket_count > 0:p
self.rocket_count -= 1
if self.rocket_count > 0:
self.rocket_create_count = self.ROCKET_CREATE_COUNT_MAX
#self.createRocketSprite()
# Rocket vs Monster
if self.is_collided(self.rocket_sp,self.monster_sp):
#print("rocket vs monster [%s][%s]" % (self.rocket_sp.position,self.monster_sp.position))
#self.spMonster.remove_from_parent()
act = Action.fade_to(0.0, 1.0,TIMING_LINEAR)
self.monster_sp.run_action(act)
self.rocket_sp.run_action(act)
if self.monster_count > 0:
self.monster_count -= 1
if self.monster_count > 0:
self.monster_create_count = self.MONSTER_CREATE_COUNT_MAX
#self.createMonsterSprite()
if self.rocket_count > 0:
self.rocket_count -= 1
if self.rocket_count > 0:
self.rocket_create_count = self.ROCKET_CREATE_COUNT_MAX
#self.createRocketSprite()
# invadar vs misille
if self.is_collided(self.invader_sp,self.misile_sp):
if self.invader_sp.img_no == 0 or self.invader_sp.img_no == 1:
self.misile_sp.remove_from_parent()
#self.misile_sp.position = self.rocket_sp.position
self.invader_sp.img_no = 2 # red
self.invader_erase_point = self.invader_sp.position.x + self.INVADER_ERASE_POINT
#print("invader vs missile")
#console.alert('invader vs missile')
#result = dialogs.text_dialog(title="invader vs missile")
#衝突確認
def is_collided(self,my, target):
dx = abs(my.position.x - target.position.x)
dy = abs(my.position.y - target.position.y)
return abs(sqrt(dx **2 + dy **2)) < 50
if name == 'main':
SpriteNode('INVADER.png')
run(GameScene())