This time, I created a 2D action scrolling process with Pythonista + scene.
Scroll the screen when the character moves. When you move to the edge of the screen, stop scrolling so that you can move freely.
The implemented processing is the following two. ・ Screen scroll ・ Screen edge processing
It is a process to scroll the screen when the character moves. While scrolling, the character's position remains the same, and scrolling is expressed by moving the background and items in the opposite direction of the character's movement.
The code is as follows. Add to the update () method.
python
def update(self):
g = gravity()
x = self.player.position.x
y = self.player.position.y
#Left and right movement
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)
If you do not prepare a border, the character will move endlessly to a position without a background, so a border is required at the edge of the screen.
When you reach the edge of the screen, stop scrolling and switch to moving the character. Scroll again when you move away from the edge of the screen.
The code is as follows. Judge "whether the character is at the edge of the screen" and if it is at the edge, interrupt scrolling and switch to moving the character.
python
def update(self):
g = gravity()
x = self.player.position.x
y = self.player.position.y
#Left and right movement
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
#Add from here--------------------------------------------------------------------------
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
#Left and right movement
x = max(0, min(self.size.w, x + distance))
self.player.position = (x, y)
else:
#Add up to here--------------------------------------------------------------------------
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)
I will omit the explanation of the processing that is not related to scrolling.
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):
#Background settings
self.background_color = '#004f82'
ground = Node(parent=self)
x = 0
#Ground height
self.base_height = 50
self.stage_size = self.size.w * 5
#Background settings
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
}
)
#Player initial settings
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)
#Jump button initial settings
self.jump = 'ready'
self.jump_button = SpriteNode('emj:Blue_Circle', position=(320,50))
self.add_child(self.jump_button)
#Initial setting of attack button
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
#Left and right movement
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)
#collision detection
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
#Left and right movement
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):
#Get the tapped position
touch_loc = self.point_from_scene(touch.location)
#Jump if the tapped position is a button
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):
#Processing when ascending
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'
#Processing when falling
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
#collision detection
def check_item_hit(self, items, score=100):
#If it matches vertically and horizontally, add the score and delete the item
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)
How to use Pythonista is also summarized in the blog. Actions other than scrolling the above code are explained on the blog. Summary of how to use Pythonista
Recommended Posts