...或者如何使用ipad消磨时间,仅此而已...你好
你在说什么
不幸的是,平板电脑尚未取代计算机。 但是乘车/飞行至关重要。 因此,我寻找了ipad底下的东西,实际上今天我将在Pythonista上进行游戏。
我们该怎么办?
最简单的程序,例如晶体(是的,是的,就是您在地铁上玩的程序)。 俄罗斯方块,蛇,填充-任何新手,只要有一点了解,都将在30分钟内写出它们。 在过场动画下-屏幕截图,教程,代码。
以下是我搞砸了的一些屏幕截图:
免责声明本文不仅专门针对初学者(但了解python),并且不允许您在十分钟内或任何现成的应用程序中创建坦克世界,但从编程宗教的角度出发,作者也不保证绝对美观且正确的代码(尽管他尝试过) 。 而且pythonista的示例和文档中也有一些东西被盗。
所有代码将在末尾给出。了解pythonista中的图形
汇入from scene import * import random
立即创建场景:
class Game(Scene): def setup(self): self.background_color = "green" run(Game(), LANDSCAPE)
好吧,让我们立即开始。 您应该有一个绿屏。 让我们做一些很酷的事情,方法是将更新方法(系统本身调用)添加到Game类中,并为其更改背景颜色。
class Game(Scene):
现在,我们的屏幕从黄色平滑过渡到白色,反之亦然。

现在创建一些对象。 我们还在setup方法中创建它:
class Game(Scene): def setup(self): self.background_color = "white" mypath = ui.Path.rect(0, 0, 50, 50) self.obj = ShapeNode(mypath) self.obj.color = "purple"
我们设置线(mypath),在其上创建一个ShapeNode,将其指向一种颜色,然后指定一个父对象(本质上是相同的-在创建时指定一个父对象,即ShapeNode(* ...,parent = self)或self.add_child (obj))。
好吧,在Game.update()中,我们更改对象(元组)的位置,它以像素为单位,从左下角开始计数。
请注意,我们不需要重新绘制场景(尽管有可能)。 其父作为场景的对象和节点(或其某些子对象)将自己重新绘制
我们在本节中要介绍的最后一件事是touch_began(以及touch_moved和touch_ended)。 很容易猜到,该方法可以捕获屏幕上的点击。 让我们尝试一下:
class Game(Scene): def touch_began(self, touch): mypath = ui.Path.oval(0, 0, 50, 50) obj = ShapeNode(mypath) obj.color = (0.5, 0.5, 1.0) self.add_child(obj) obj.position = touch.location

每次您在屏幕上单击时,我们都会创建一个圆圈,单击的位置是touch.location。
准备写一条蛇
游戏机制蛇是正方形的阵列,当头部移动时-第二块移动到第一个,第三个移动到第二个,依此类推。为找出头部与尾巴的交点,我们将其与每条尾巴进行比较
我们删除所有书面代码,因为我们想或多或少地做到美观(但是,当然,我们会骑自行车)。
首先,让我们创建PhyObj类:
class PhyObj: def __init__(self, path, color, parent): self.graph_obj = ShapeNode(path, parent=parent) self.parent = parent self.graph_obj.color = color def setpos(self, x, y): self.graph_obj.position = (x, y) def getpos(self): return self.graph_obj.position def move(self, x, y): self.graph_obj.position += (x, y)
我认为这里的一切都很微不足道。 在类本身内部,我们创建了一个节点,并描述了一些使我们的代码更具可读性的方法。
holivary就我个人而言,我更喜欢先创建具有许多重复方法和属性的低级类,但随后高级类中的代码将变得非常漂亮且易读。
PhyObj是我们游戏中最低级别的对象,实际上它是抽象的物理对象。
蛇描述
现在,我们需要描述这条蛇,由于它是由碎片组成的,因此我们将首先描述一条:
class Tile(PhyObj): def __init__(self, parent, size, margin=4): super().__init__(ui.Path.rect(0, 0, size[0] - margin, size[1] - margin), "#66FF66", parent) def die(self): self.graph_obj.color = "red"
在构造函数中,我们调用类的父方法,并给我们自己指定形状和颜色。 需要留有边距,以使正方形不会粘在一起并形成某种网格。
class Game(Scene): def setup(self): self.tile = Tile(self, (40, 40)) self.tile.setpos(100, 100)
结果应该是:

但是例如,为什么我们需要保证金:
class Game(Scene): def setup(self): tile1 = Tile(self, (40, 40)) tile1.setpos(100, 100) tile2 = Tile(self, (40, 40)) tile2.setpos(140, 100)

好了,现在您需要从这些碎片上粘蛇。 我们需要一个初始化方法和一个移动方法。
首先,创建初始化:
class Snake: def __init__(self, length, width, initpos, parent): self.width = width
让我们尝试立即绘制它:
class Game(Scene): def setup(self): self.snake = Snake(10, 40, (200, 200), self)

好吧,添加移动方法。
class Snake: def move(self, x, y): for i in range(len(self.tiles) - 1, 0, -1): self.tiles[i].setpos(*self.tiles[i - 1].getpos()) self.tiles[0].move(x * self.width, y * self.width)
首先,我们将最后一个移到倒数第二个,然后将倒数第二个移到倒数第二个,然后将第二个移到第一个。 以及第一个(x,y)。
实际上,我们的蛇直线移动得很好。 让我们尝试:
class Game(self):
如果您设法看到,那么她应该爬行了。 事实是,更新被调用得非常频繁(顺便说一下,可以选择以相同的间隔),因此我们需要考虑自上次调用以来已经经过了多少时间,并等待直到其“累积”了足够的时间。
简而言之,我们这样做:
class Game(Scene): def time_reset(self): self.last_time = self.t def time_gone(self, t): if self.t - self.last_time > t: res = True self.time_reset() else: res = False return res def setup(self): self.snake = Snake(10, 40, (200, 200), self) self.time_reset() def update(self): if self.time_gone(0.3): self.snake.move(0, 1)
如果经过的时间超过t,则time_gone返回True。 现在,蛇将每0.3秒移动一次。 奏效了吗?

管理学
现在您需要进行控制,即在所有四个方向上转弯:

class Game(Scene):
现在,我们需要进行touch_began处理以了解用户插入的区域。 实际上,结果并没有我想的那么有趣,因此您可以在此处简单地复制:
class Game(Scene):
好吧,现在尝试转身

制定了主要机制,仍然需要检查碰撞和苹果。
尾巴碰撞
让我们开始检查并向蛇添加find_collisions方法
class Snake:
现在我们可以获得一对相交的细胞。 我想将它们涂成红色,将die方法添加到Tile中:
class Tile(PhyObj):
添加检查以更新和更改设置:
class Game(Scene):
我怎么了:

它仍然是用来做苹果的。
伸长率和苹果
我们将加长蛇,并使它看起来更漂亮,将根据后两个添加新的链接,即:

将方法添加到蛇:
class Snake:
find_dir查找女主人公的尾巴尖的方向。 追加,很容易猜到,添加了一个单元格。 在Game中添加另一个snake_lengthen方法:
class Game(Scene):
最后一行是需要的,以便蛇稍等一会儿,并且用户设法看到添加了那条。
要确定某条蛇是否与某条线相交,请向该条蛇添加相交方法。
class Snake:
万岁,它仍然只是创建一个苹果。 实际上,我们一口气描述了苹果:
class Apple(PhyObj): def __init__(self, width, size, parent): super().__init__(ui.Path.oval(0, 0, size[0], size[1]), "#55AAFF", parent) self.parent = parent self.width = width self.dislocate() def dislocate(self): a = random.randint(2, int(self.parent.size.w / self.width) - 2) b = random.randint(2, int(self.parent.size.h / self.width) - 2) self.setpos(a * self.width, b * self.width)
需要这种奇怪的随机性来使我们的靶心适应网格。 这样就不必寻找枪口和苹果之间的距离并比较其pyre-pyr。 就在ifas上。 让我们去更新并在此函数的末尾添加非常简单的行:
class Game(Scene):
好吧,一切似乎都发生了,现在如果蛇撞到苹果,蛇会伸长,而撞到苹果则死。

红利
您可以制作音效:
import sound class Game(Scene):
进行平滑运动:
class Game(Scene):
换句话说,我们更改了位置PhyObj的逻辑。 以前,我们专注于图形元素的位置,现在有一个单独的逻辑位置字段(即用于游戏逻辑的字段),并且图形元素的位置现在是自由的,可以以自己的方式更改。 即,使用“动作”,我们为她留出了并行流,并在其中进行移动。
这样一条光滑的蛇竟然是:

最后,加上蛇的长度的标签:
class Game(Scene):

朋友们,谢谢您的关注! 如果不清楚,请询问。 而且,如果这很有趣-我会继续讲,但仍有一些要说的(但是本文已经相当长了)。
所有蛇码 from scene import * import random import math import sound class PhyObj: def __init__(self, path, color, parent): self.graph_obj = ShapeNode(path, parent=parent) self.parent = parent self.graph_obj.color = color self.pos = self.graph_obj.position def setpos(self, x, y, t=0.0): self.pos = (x, y) self.graph_obj.run_action(Action.move_to(x, y, t)) def getpos(self): return self.pos def move(self, x, y, t=0.0): self.pos = (self.pos[0] + x, self.pos[1] + y) self.graph_obj.run_action(Action.move_by(x, y, t)) class Tile(PhyObj): def __init__(self, parent, size, margin=4): super().__init__(ui.Path.rect(0, 0, size[0] - margin, size[1] - margin), "#66FF66", parent) def die(self): self.graph_obj.color = "red" class Snake: def __init__(self, length, width, initpos, parent): self.width = width self.tiles = [Tile(parent, (width, width)) for i in range(length)] for i, tile in enumerate(self.tiles): tile.setpos(initpos[0] + i * self.width, initpos[1]) self.parent = parent def move(self, x, y): for i in range(len(self.tiles) - 1, 0, -1): self.tiles[i].setpos(*self.tiles[i - 1].getpos(), self.parent.GLOBAL_TIMING) self.tiles[0].move(x * self.width, y * self.width, self.parent.GLOBAL_TIMING) def find_collisions(self): for i in range(1, len(self.tiles)): if self.tiles[i].getpos() == self.tiles[0].getpos(): return self.tiles[i], self.tiles[0] return False def find_dir(self, x1, y1, x2, y2): if x1 == x2 and y1 > y2: return (0, 1) elif x1 == x2 and y1 < y2: return (0, -1) elif y1 == y2 and x1 > x2: return (1, 0) elif y1 == y2 and x1 < x2: return (-1, 0) else: assert False, "Error!" def append(self): if len(self.tiles) > 1: lastdir = self.find_dir(*self.tiles[-1].getpos(), *self.tiles[-2].getpos()) else: lastdir = (-self.parent.dir[0], -self.parent.dir[1]) self.tiles.append(Tile(self.parent, (self.width, self.width))) x_prev, y_prev = self.tiles[-2].getpos() self.tiles[-1].setpos(x_prev + lastdir[0] * self.width, y_prev + lastdir[1] * self.width) def getpos(self): return self.tiles[0].getpos() def intersect(self, x, y): return self.getpos() == (x, y) class Apple(PhyObj): def __init__(self, width, size, parent): super().__init__(ui.Path.oval(0, 0, size[0], size[1]), "#55AAFF", parent) self.parent = parent self.width = width self.dislocate() def dislocate(self): a = random.randint(2, int(self.parent.size.w / self.width) - 2) b = random.randint(2, int(self.parent.size.h / self.width) - 2) self.setpos(a * self.width, b * self.width) class Game(Scene): def snake_lengthen(self): self.snake.append() self.time_reset() sound.play_effect('arcade:Powerup_1', 0.25, 0.8) def time_reset(self): self.last_time = self.t def time_gone(self, t): if self.t - self.last_time > t: res = True self.time_reset() else: res = False return res def setup(self): self.game_on = False self.GLOBAL_TIMING = 0.2 self.GLOBAL_WIDTH = 40 self.apple = Apple(self.GLOBAL_WIDTH, (50, 50), self) self.snake = Snake(30, self.GLOBAL_WIDTH, (200, 200), self) self.time_reset() self.dir = (0, 1) self.label = LabelNode("", font=("Chalkduster", 20), parent=self, position=(self.size.w / 2, self.size.h - 100)) self.update_labels() self.game_on = True def update_labels(self): self.label.text = "Length: " + str(len(self.snake.tiles)) def update(self): if not self.game_on: return col = self.snake.find_collisions() if col: for tile in col: tile.die() self.game_on = False if self.time_gone(self.GLOBAL_TIMING): self.snake.move(*self.dir) if self.snake.intersect(*self.apple.getpos()): self.snake_lengthen() self.apple.dislocate() self.update_labels() def touch_began(self, touch): ws = touch.location[0] / self.size.w hs = touch.location[1] / self.size.h aws = 1 - ws if ws > hs and aws > hs: self.dir = (0, -1) elif ws > hs and aws <= hs: self.dir = (1, 0) elif ws <= hs and aws > hs: self.dir = (-1, 0) else: self.dir = (0, 1) run(Game(), LANDSCAPE)
水晶代码WhiteBlackGoose版有趣的是,在完成之后,我在pythonista本身的示例中发现了非常相似的东西。 但我还有更多功能:)
from scene import * from math import pi from random import uniform as rnd, choice, randint import sys import random A = Action sys.setrecursionlimit(1000000) colors = ['pzl:Green5', "pzl:Red5", "pzl:Blue5"] + ["pzl:Purple5", "pzl:Button2"] + ["plf:Item_CoinGold"] global inited inited = False class Explosion (Node): def __init__(self, brick, *args, **kwargs): Node.__init__(self, *args, **kwargs) self.position = brick.position for dx, dy in ((-1, -1), (1, -1), (-1, 1), (1, 1)): p = SpriteNode(brick.texture, scale=0.5, parent=self) p.position = brick.size.w/4 * dx, brick.size.h/4 * dy p.size = brick.size d = 0.6 r = 30 p.run_action(A.move_to(rnd(-r, r), rnd(-r, r), d)) p.run_action(A.scale_to(0, d)) p.run_action(A.rotate_to(rnd(-pi/2, pi/2), d)) self.run_action(A.sequence(A.wait(d), A.remove())) class Brick (SpriteNode): def __init__(self, brick_type, *args, **kwargs): img = colors[brick_type] SpriteNode.__init__(self, img, *args, **kwargs) self.brick_type = brick_type self.is_on = True self.lf = True self.enabled = True def destroy(self): self.remove_from_parent() self.is_on = False def mark(self): self.lf = False def demark(self): self.lf = True class Game(Scene): def brickgetpos(self, i, j): return (self.Woff + j * self.W, self.Hoff + i * self.H) def brick(self, ty, i, j): b = Brick(ty, size=(self.W, self.H), position=self.brickgetpos(i, j), parent=self.game_node) b.rotation = random.random() return b def random_brick_type(self): if random.random() < 0.992: return random.randint(0, 3) else: if random.random() < 0.8: return 5 else: return 4 def setup(self): FONT = ('Chalkduster', 20) self.score_label = LabelNode('Score: 0', font=FONT, position=(self.size.w/2-100, self.size.h-40), parent=self) self.score = 0 self.last_score_label = LabelNode('Delta: +0', font=FONT, position=(self.size.w/2-300, self.size.h-40), parent=self) self.last_score = 0
晶体工作演示: