Créer un défilement d'écran avec Pythonista + scene

Cette fois, j'ai créé un processus de défilement pour les actions 2D avec Pythonista + scene.

Aperçu du programme

Faites défiler l'écran lorsque le personnage se déplace. Lorsque vous vous déplacez vers le bord de l'écran, arrêtez de faire défiler pour pouvoir vous déplacer librement.

Traitement mis en œuvre

Le traitement mis en œuvre est le suivant. ・ Défilement d'écran ・ Traitement des bords de l'écran

Défilement d'écran

C'est un processus pour faire défiler l'écran lorsque le personnage se déplace. Pendant le défilement, la position du caractère reste la même, et le défilement est exprimé en déplaçant l'arrière-plan et les éléments dans la direction opposée du mouvement du personnage.

Pythonista_scroll.png

Le code est comme suit. Ajoutez à la méthode update ().

python



def update(self):
	g = gravity()
	x = self.player.position.x
	y = self.player.position.y
	#Mouvement à gauche et à droite
	if abs(g.x) > 0.05:
		max_speed = 40
		self.update_position(max_speed)
	else:
		self.player.texture = standing_texture
		self.walk_step = -1
		
def update_position(self, max_speed):
	g = gravity()
	x = self.player.position.x
	y = self.player.position.y
	distance = g.x * max_speed 
		
	x = self.size.w/2
	self.player.position = (x, y)
	for t in self.tiles:
		t['tile1'].position = (t['tile1'].position.x - distance, t['tile1'].position.y)
		t['tile2'].position = (t['tile2'].position.x - distance, t['tile2'].position.y)
	for item in self.items:
		item.position = (item.position.x - distance, item.position.y)
	for item in self.stars:
		item.position = (item.position.x - distance, item.position.y)
	for item in self.mushrooms:
		item.position = (item.position.x - distance, item.position.y)

Traitement des bords de l'écran

Si vous ne préparez pas de bordure, le personnage se déplacera indéfiniment vers une position sans arrière-plan, une bordure est donc requise au bord de l'écran.

Lorsque vous atteignez le bord de l'écran, arrêtez le défilement et passez au déplacement du personnage. Faites défiler à nouveau lorsque vous vous éloignez du bord de l'écran.

Le code est comme suit. Jugez "si le personnage est au bord de l'écran" et s'il est au bord, interrompez le défilement et passez au déplacement du personnage.

python



def update(self):
	g = gravity()
	x = self.player.position.x
	y = self.player.position.y
	#Mouvement à gauche et à droite
	if abs(g.x) > 0.05:
		max_speed = 40
		self.update_position(max_speed)
	else:
		self.player.texture = standing_texture
		self.walk_step = -1
		
def update_position(self, max_speed):
	g = gravity()
	x = self.player.position.x
	y = self.player.position.y
	distance = g.x * max_speed 
#Ajouter à partir d'ici--------------------------------------------------------------------------
	self.move_count = max(0, min(self.move_count + distance, self.stage_size))
	if self.move_count < self.size.w/2 or self.move_count >= self.stage_size - self.size.w/2:
		self.player.x_scale = cmp(g.x, 0)
		step = int(self.player.position.x / 40) % 2
		if step != self.walk_step:
			self.player.texture = walk_textures[step]
			self.walk_step = step
		#Mouvement à gauche et à droite
		x = max(0, min(self.size.w, x + distance))
		self.player.position = (x, y)
	else:
#Ajouter ici--------------------------------------------------------------------------
		x = self.size.w/2
		self.player.position = (x, y)
		for t in self.tiles:
			t['tile1'].position = (t['tile1'].position.x - distance, t['tile1'].position.y)
			t['tile2'].position = (t['tile2'].position.x - distance, t['tile2'].position.y)
		for item in self.items:
			item.position = (item.position.x - distance, item.position.y)
		for item in self.stars:
			item.position = (item.position.x - distance, item.position.y)
		for item in self.mushrooms:
			item.position = (item.position.x - distance, item.position.y)

Tâche

  1. Sauter au bord de l'écran peut se déformer vers le centre de l'écran.
  2. L'animation de marche s'arrête car le personnage défilant n'est pas traité comme en mouvement.

Code complet

Je vais omettre l'explication du traitement qui n'est pas lié au défilement.

python



# coding: utf-8

from scene import *
from sound import *

def cmp(a, b):
	return ((b > a) - (b < a))
	
	
standing_texture = Texture('emj:Ghost')
walk_textures = [Texture('emj:Ghost'), Texture('emj:Ghost')]

class Game (Scene):
	def setup(self):
		#Paramètres d'arrière-plan
		self.background_color = '#004f82'
		ground = Node(parent=self)
		x = 0
		#Hauteur du sol
		self.base_height = 50
		self.stage_size = self.size.w * 5
		#Paramètres d'arrière-plan
		self.tiles = []
		while x <= self.stage_size + 128:
			tile1 = SpriteNode('plf:Ground_GrassHalf_mid', position=(x - 50, self.base_height))
			ground.add_child(tile1)
			
			tile2 = SpriteNode('plf:Ground_GrassCenter', position=(x - 50, self.base_height-32))
			ground.add_child(tile2)
			x += 64
			self.tiles.append(
				{
					'tile1' : tile1,
					'tile2' : tile2
				}
			)
			
		#Paramètres initiaux du lecteur
		self.player_height = self.base_height + 32
		self.player = SpriteNode('emj:Ghost')
		self.player.anchor_point = (0.5, 0)
		self.player.position = (self.size.w/2, self.player_height)
		self.add_child(self.player)
		#Paramètres initiaux du bouton de saut
		self.jump = 'ready'
		self.jump_button = SpriteNode('emj:Blue_Circle', position=(320,50))
		self.add_child(self.jump_button)
		#Réglage initial du bouton d'attaque
		self.attack_button = SpriteNode('emj:Blue_Circle', position=(250,50), color='red')
		self.add_child(self.attack_button)
		
		self.bullet = SpriteNode('shp:sun')
		self.bullet.position = -1000, -1000
		self.add_child(self.bullet)
		
		mushroom = SpriteNode('emj:Mushroom')
		mushroom.anchor_point = (0.5, 0)
		mushroom.position = (self.size.w * 3, self.player_height)
		self.add_child(mushroom)
		self.mushrooms = [mushroom]
		
		star = SpriteNode('plc:Star')
		star.anchor_point = (0.5, 0)
		star.position = (self.size.w + self.size.w/2, self.player_height + 300)
		self.add_child(star)
		self.stars = [star]
		
		self.items = []
		for i in range(0, 5):
			for j in range(0,2):
				item = SpriteNode('plf:HudCoin')
				item.anchor_point = (0.5, 0)
				item.position = (self.size.w + 80 + i * 50, self.player_height + 100 + 60 * j)
				self.add_child(item)
				self.items.append(item)
		self.charge = False
		self.power = 0
		self.disp_lock = False
		self.move_count = self.size.w/2
		
		score_font = ('Futura', 40)
		self.score_label = LabelNode('0', score_font, parent=self)
		# The label is centered horizontally near the top of the screen:
		self.score_label.position = (self.size.w/2, self.size.h - 70)
		# The score should appear on top of everything else, so we set the `z_position` attribute here. The default `z_position` is 0.0, so using 1.0 is enough to make it appear on top of the other objects.
		self.score_label.z_position = 1
		self.score = 0
		self.walk_step = -1
		
		
	def update(self):
		g = gravity()
		x = self.player.position.x
		y = self.player.position.y
		#Mouvement à gauche et à droite
		if abs(g.x) > 0.05:
			max_speed = 40
			self.update_position(max_speed)
		else:
			self.player.texture = standing_texture
			self.walk_step = -1
		self.check_jump(x,y)
		if self.charge and self.power < 100:
			self.power += 1
			
		for item in self.mushrooms:
			item.position = (item.position.x -1, item.position.y)
		#Détection de collision
		self.check_item_hit(self.mushrooms, score=500)
		self.check_item_hit(self.items)
		self.check_item_hit(self.stars, score=1500)
		
		
	def update_position(self, max_speed):
		g = gravity()
		x = self.player.position.x
		y = self.player.position.y
		distance = g.x * max_speed 
		
		self.move_count = max(0, min(self.move_count + distance, self.stage_size))
		if self.move_count < self.size.w/2 or self.move_count >= self.stage_size - self.size.w/2:
			self.player.x_scale = cmp(g.x, 0)
			step = int(self.player.position.x / 40) % 2
			if step != self.walk_step:
				self.player.texture = walk_textures[step]
				self.walk_step = step
			#Mouvement à gauche et à droite
			x = max(0, min(self.size.w, x + distance))
			self.player.position = (x, y)
		else:
			x = self.size.w/2
			self.player.position = (x, y)
			for t in self.tiles:
				t['tile1'].position = (t['tile1'].position.x - distance, t['tile1'].position.y)
				t['tile2'].position = (t['tile2'].position.x - distance, t['tile2'].position.y)
			for item in self.items:
				item.position = (item.position.x - distance, item.position.y)
			for item in self.stars:
				item.position = (item.position.x - distance, item.position.y)
			for item in self.mushrooms:
				item.position = (item.position.x - distance, item.position.y)
		
	def touch_began(self, touch):
		self.power = 0
		self.charge = True
		
	def touch_ended(self, touch):
		#Obtenez la position tapée
		touch_loc = self.point_from_scene(touch.location)
		#Sauter si la position tapée est un bouton
		if touch_loc in self.jump_button.frame:
			if self.jump == 'ready':
				play_effect('game:Boing_1')
				self.jump = 'up'
		if touch_loc in self.attack_button.frame:
			if self.jump == 'ready':
				x, y = self.player.position
				self.bullet.position = x, y + 50
				move = Action.move_to(x, self.player_height +1000, 0.5 ,TIMING_LINEAR)
				self.bullet.run_action(move)
				
	def check_jump(self, x, y):
		#Traitement en montant
		if self.jump == 'up':
			max_height = 180 + self.power
			up_speed = 10
			y = max(self.player_height, min(self.size.h, y + up_speed))
			self.player.position = (x, y)
			if y > max_height + self.player_height:
				self.jump = 'down'
				
		#Traitement en cas de chute
		if self.jump == 'down':
			down_speed = 10
			y = max(self.player_height, min(self.size.h, y - down_speed))
			self.player.position = (x, y)
			if y == self.player_height:
				self.jump = 'ready'
				self.charge = False
				
				
	#Détection de collision
	def check_item_hit(self, items, score=100):
		#S'il y a une correspondance verticale et horizontale, ajoutez le score et supprimez l'élément.
		for item in items:
			if abs(self.player.position.x - item.position.x) < 30 and abs(self.player.position.y - item.position.y) < 30:
				item.remove_from_parent()
				self.score += score
				items.remove(item)
				self.score_label.text = str(self.score)
			if abs(self.bullet.position.x - item.position.x) < 30 and abs(self.bullet.position.y - item.position.y) < 30:
				item.remove_from_parent()
				self.score += score
				items.remove(item)
				self.score_label.text = str(self.score)
				
if __name__ == '__main__':
	run(Game(), PORTRAIT, show_fps=True)

Exemple d'exécution (animation gif)

L'utilisation de Pythonista est également résumée dans le blog. Les actions autres que le défilement du code ci-dessus sont expliquées sur le blog. Résumé de l'utilisation de Pythonista

Recommended Posts

Créer un défilement d'écran avec Pythonista + scene
Créer un écran de mise à jour avec Django Updateview
Jouer avec l'implémentation de l'interface utilisateur de Pythonista [Éléments d'écran]
Créez des jeux avec Pygame
Créer un filtre avec scipy
[Python] Créez un écran de spécification de chemin de fichier et de dossier avec tkinter
[Python] Créer un écran pour le code d'état HTTP 403/404/500 avec Django
Créer un environnement avec virtualenv
Créez Cloud TPU avec tf-nightly
Créer une API avec Django
Créer / rechercher / créer une table avec PynamoDB
Créer un gif 3D avec python3
tracé Créer un graphique avec un bouton
Créer une page d'accueil avec django
Changement d'écran / transition d'écran avec Tkinter
Créer une visionneuse d'images avec Tkinter
Transfert de fichiers bidirectionnel dans Pythonista 3
Créez des règles personnalisées avec ElastAlert
Créez une carte des brevets avec Streamlit
Créer un écran de connexion Django
Créer un répertoire avec python
Créer un fichier xlsx avec XlsxWriter
Écran divisé en 3 avec keyhac