スネークはノキアの携帯電話の古典的なゲームです。Turleモジュールを使用して独自のスネークゲームを実装できます。
効果図は以下の通りです
Snake Snakeプログラムでは、要するに、解決する必要のあるいくつかの問題があります。
- スネークアウトを初期化する
- ヘビは動くことができます
- ヘビを上下に動かすように制御できます
- ランダムな食べ物を生成する
- ヘビは食べ物を食べることができます
- ヘビは背が高くなることがあります
- ヘビが壁にぶつかるか、自分自身にぶつかって死ぬ
- 関連するスコアと情報を表示する
上記の問題を1つずつ解決し、最終的な手順も実行します。
解決:
- スネークを初期化する原理は、実際には前のトータスレースと同じです。一度に3つの正方形をインスタンス化し、座標を調整してまとめます。
- ヘビはどのように動きますか?初期化後、3つの正方形を組み合わせてリストに入れることができます。最初の正方形は当然ヘビの頭で、最後の正方形はヘビの尾です。移動するたびに、ヘビの尾から前方にループします。正方形は前の正方形の座標に移動します。スネークヘッドの前に座標がない場合、デフォルトで前方に実行されます。その結果、ヘビは前方に急いで移動します。
- これは、画面のキーボード監視イベントによって解決されます。機能がトリガーされるたびに、スネークヘッドの角度が内部で調整されます。
- ランダムフードはタートルクラスを直接継承できます。色とサイズを初期化した後、座標生成をランダムに指定できます
- フードとスネークヘッド自体のサイズが設定されているので、スネークヘッドとフードの間の距離を判断します。距離関数を使用して、接触していても一定の座標長より短いかどうかを判断できます。
- スネークの長さとスネークの初期化の操作は基本的に同じです。新しいインスタンスを作成し、スネークテールに合わせて座標を調整し、リストに追加します。
- ヘビの頭の座標を判断し、境界座標に達しているのか、それとも自分の体の座標に近いのかを確認することで、衝突したかどうかを知ることができます。
- 表示内容はturtle.write関数で実現でき、フォントと座標を調整するだけです。
上記の問題に加えて、デフォルトのアニメーション効果をオフにする必要があることに注意する別のポイントがあります。そうしないと、体のすべての正方形がスローモーションで表示され、奇妙な毛虫が動いているように見えます。解決策は、アニメーションエフェクトをオフにすることです。その後、すべての正方形が移動するたびに、インターフェイスを手動で更新して、継続的なエフェクトが蛇全体が動いているように見えるようにします。
そうは言っても、最後にソースコードを見てみましょう。
たった4つのpyファイル、メインファイルは他の3つのタイプのファイルを呼び出します
main.py
from turtle import Screen
import time
from snake import Snake
from food import Food
from scoreboard import Scoreboard
#初始化画布,设置长度,宽度和标题
screen = Screen()
screen.setup(width=600, height=600)
screen.bgcolor("black")
screen.title("Snake Game")
#tracer设置为0的作用是关闭动画效果,我们通过timer设置延时,然后通过update手动刷新界面,否则默认的动画效果看起来就是每个方块的移动效果
#想象一下GIF或者CRT显示器的原理,多个画面连续刷新,看起来就像动起来一样
screen.tracer(0)
#实例化三个对象
snake_segments = Snake()
food = Food()
scoreboard = Scoreboard()
#监听上下左右的键盘操作
screen.listen()
screen.onkey(snake_segments.up, "Up")
screen.onkey(snake_segments.down, "Down")
screen.onkey(snake_segments.left, "Left")
screen.onkey(snake_segments.right, "Right")
#布尔值判断是否结束游戏
game_is_on = True
while game_is_on:
#每次停顿0.1秒后刷新一下界面,然后蛇移动一下
screen.update()
time.sleep(0.1)
snake_segments.move()
# 如果蛇头碰见食物了,那么食物刷新随机生成一下,分数加一,蛇身长度加一
if snake_segments.head.distance(food) < 15:
print("yum yum yum")
food.refresh()
scoreboard.addscore()
snake_segments.add_segment()
# 如果蛇头撞墙了,那么Game over
if snake_segments.head.xcor() > 280 or snake_segments.head.xcor() < -280 or snake_segments.head.ycor() > 280 or snake_segments.head.ycor() < -280:
game_is_on = False
scoreboard.gameover()
# 如果蛇头撞到身子了,那么Game over,注意列表是从第二节开始的,排除蛇头
for seg in snake_segments.segments[1:]:
if snake_segments.head.distance(seg) < 10:
game_is_on = False
scoreboard.gameover()
screen.exitonclick()
scoreboard.py
from turtle import Turtle
ALIGNMENT="center"
FONT=("Arial",20,"normal")
#显示分数和Game over等标记
class Scoreboard(Turtle):
def __init__(self):
super().__init__()
self.color('white')
self.penup()
self.hideturtle()
self.score=0
self.updatescore()
def updatescore(self):
self.goto(0, 270)
self.write(f"SCORE = {self.score}",True, align=ALIGNMENT,font=FONT)
self.goto(0,250)
# self.write("-"*300,True, align=ALIGNMENT,font=FONT)
def addscore(self):
self.score+=1
self.clear()
self.updatescore()
def gameover(self):
#self.clear()
self.goto(0,0)
self.write(f"GAME OVER",True, align=ALIGNMENT, font=FONT)
snake.py
from turtle import Turtle
MOVE_DISTANCE=20
class Snake:
#初始化的时候,蛇有三节,一字排开,放到一个列表里
def __init__(self):
self.segments = []
for i in range(3):
seg = Turtle(shape="square")
seg.color('white')
seg.penup()
seg.goto(0 - 20 * i, 0)
self.segments.append(seg)
self.head=self.segments[0]
#这个是最核心的部分,每次移动的时候,从蛇尾巴往前循环,每个方块往上一个方块的坐标移动,蛇头自动往前跑
def move(self):
for seg_num in range(len(self.segments) - 1, 0, -1):
new_x = self.segments[seg_num - 1].xcor()
new_y = self.segments[seg_num - 1].ycor()
self.segments[seg_num].goto(new_x, new_y)
self.segments[0].forward(MOVE_DISTANCE)
#蛇头往上跑
def up(self):
if self.head.heading() !=270:
self.head.setheading(to_angle=90)
#蛇头往下跑
def down(self):
if self.head.heading() != 90:
self.head.setheading(to_angle=270)
#蛇头往左跑
def left(self):
if self.head.heading() !=0:
self.head.setheading(to_angle=180)
#蛇头往右跑
def right(self):
if self.head.heading() !=180:
self.head.setheading(to_angle=0)
#蛇的身子加1,原理是新创建一个实例,然后放到蛇尾巴的位置
def add_segment(self):
seg = Turtle(shape="square")
seg.color('white')
seg.penup()
tail = self.segments[-1]
seg.goto(tail.xcor(),tail.ycor())
self.segments.append(seg)
food.py
from turtle import Turtle
import random
class Food(Turtle):
def __init__(self):
super().__init__()
self.shape('circle')
self.penup()
#self.shapesize(stretch_len=0.5,stretch_wid=0.5)
self.color('blue')
self.speed('fastest')
# self.goto(random.randint(-280,280),random.randint(-280,280))
self.refresh()
def refresh(self):
self.goto(random.randint(-280, 280), random.randint(-280, 260))
とてもシンプル