LoginSignup
0
1

More than 1 year has passed since last update.

pythonista3でゲーム作りにチャレンジ

Last updated at Posted at 2022-05-20

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())

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1