找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 303|回复: 0

[教程] renpy里的贪吃蛇!

[复制链接]
发表于 2025-10-12 21:20:48 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
本帖最后由 Aaron栩生阿龙 于 2025-10-14 20:56 编辑

没错又是我,几个小时前写出俄罗斯方块之后突然想到这个代码“稍微”改一下可以改成贪吃蛇,虽然已经有人做过贪吃蛇项目了(比如ZYK在去年八月发的那个),不过我这里还是相当于是多提供一个思路吧

Python部分,这里是纯Python代码:
[Python] 纯文本查看 复制代码
"""renpy
init -2 python:
"""

import random

class SnakeGame():

    def __init__(self, width=20, height=20, warp_h=False, warp_v=False):
        self.width = max(width, 10)
        self.height = max(height, 10)
        self.warp_h = warp_h
        self.warp_v = warp_v

        self.total_cells = width * height

        self.reset_game()

    def reset_game(self):
        self.board = [[0 for _ in range(self.width)] for _ in range(self.height)]
        self.score = 0
        self.gameover = 0 # 0表示游戏未失败,1表示撞墙,2表示咬到自己
        self.victory = False

        mid_x = self.width // 2
        mid_y = self.height // 2
        self.snake = [
            (mid_x, mid_y),
            (mid_x - 1, mid_y),
            (mid_x - 2, mid_y)
        ]
        self.direction = (1, 0)
        self.next_direction = (1, 0)

        self._generate_food()
        self._update_board()

    def _generate_food(self):
        available = []
        for y in range(self.height):
            for x in range(self.width):
                if self.board[y][x] == 0:
                    available.append((x, y))

        if available:
            self.food = random.choice(available)

    def _update_board(self):
        self.board = [[0 for _ in range(self.width)] for _ in range(self.height)]

        food_x, food_y = self.food
        self.board[food_y][food_x] = 3

        for index, (x, y) in enumerate(self.snake):
            display_x = x % self.width if self.warp_h else x
            display_y = y % self.height if self.warp_v else y

            if 0 <= display_x < self.width and 0 <= display_y < self.height:
                self.board[display_y][display_x] = 2 if index == 0 else 1

    def check_collision(self, head_x, head_y):
        head_x = head_x % self.width if self.warp_h else head_x
        head_y = head_y % self.height if self.warp_v else head_y

        if ((not self.warp_h and (head_x < 0 or head_x >= self.width)) or
            (not self.warp_v and (head_y < 0 or head_y >= self.height))):
            return 1

        for segment in self.snake[1:]:
            seg_x, seg_y = segment
            seg_x = seg_x % self.width if self.warp_h else seg_x
            seg_y = seg_y % self.height if self.warp_v else seg_y

            if (head_x, head_y) == (seg_x, seg_y):
                return 2

        return 0

    def move(self):
        dx1, dy1 = self.direction
        dx2, dy2 = self.next_direction
        if dx1 * dx2 + dy1 * dy2 != -1: # 向量点积,如果等于-1说明完全反向了
            self.direction = self.next_direction

        head_x, head_y = self.snake[0]
        dx, dy = self.direction
        new_head_x = head_x + dx
        new_head_y = head_y + dy

        self.gameover = self.check_collision(new_head_x, new_head_y)

        self.snake.insert(0, (new_head_x, new_head_y))

        food_x, food_y = self.food

        new_head_x = new_head_x % self.width
        new_head_y = new_head_y % self.height

        if (new_head_x, new_head_y) == (food_x, food_y):
            self.score += 1
            if len(self.snake) == self.total_cells:
                self.victory = True
            else:
                self._generate_food()
        else:
            self.snake.pop()

        self._update_board()

    def set_direction(self, direction):
        self.next_direction = direction

然后界面部分,这里是renpy代码
[RenPy] 纯文本查看 复制代码
image snake0 = Solid('#000000', xysize=(30, 30))
image snake1 = Solid('#FFFFFF', xysize=(30, 30))
image snake2 = Solid('#e7b40eff', xysize=(30, 30))
image snake3 = Solid('#e70e0eff', xysize=(30, 30))

init python:

    snakegame = SnakeGame(20, 20, False, False) # 后面两个参数用于控制地图边界是否连通

    def snake_board(st, at, snakegame):

        cells = []
        for row in snakegame.board:
            for cell in row:
                cells.append(f'snake{cell}')

        board = Grid(snakegame.width, snakegame.height, *cells)

        return board, 0.1

screen snakegame_screen(snakegame, speed=4):

    default game_pause = False

    add Solid('#FFF8', xysize=((snakegame.width+2)*30, (snakegame.height+2)*30)) align (0.5, 0.5)
    add DynamicDisplayable(snake_board, snakegame) align (0.5, 0.5)

    text '当前分数:[snakegame.score]' align (0.5, 0.0)

    key 'K_ESCAPE' action ToggleScreenVariable('game_pause')

    if not (snakegame.gameover or snakegame.victory or game_pause):
        key 'K_UP' action Function(snakegame.set_direction, (0, -1))
        key 'K_DOWN' action Function(snakegame.set_direction, (0, 1))
        key 'K_LEFT' action Function(snakegame.set_direction, (-1, 0))
        key 'K_RIGHT' action Function(snakegame.set_direction, (1, 0))

        timer 1 / speed action Function(snakegame.move) repeat True

    else:
        frame:
            modal True
            align (0.5, 0.5)
            xysize (600, 400)

            vbox:
                align (0.5, 0.5)

                $ sentence = (
                    '你赢了!\n\n你庞大的身躯占满了草地,\n现在你只想躺着不动好好晒晒太阳。' if snakegame.victory
                    else '你输了!\n\n你撞到了墙,\n话说一只蛇撞墙能把自己撞死吗?' if snakegame.gameover == 1
                    else '你输了!\n\n你咬到了自己,\n看来你真是饿了……' if snakegame.gameover == 2
                    else '游戏暂停\n\n蛇蛇正在思索下一步的路线,\n或者你只是单纯吃太多晕碳了……'
                )

                text sentence xalign 0.5 textalign 0.5
                null height 75
                hbox:
                    xalign 0.5

                    textbutton '重新开始' action [Function(snakegame.reset_game), SetScreenVariable('game_pause', False)]
                    textbutton '退出游戏' action [Function(snakegame.reset_game), Return()]

label start:
    call screen snakegame_screen(snakegame)

然后就可以开始玩了,用方向键控制移动方向,点击ESC可以暂停游戏之后也会出一期教程(和俄罗斯方块合成一期),如果有bug请及时反馈(

评分

参与人数 1活力 +300 干货 +3 收起 理由
被诅咒的章鱼 + 300 + 3 厉害了~

查看全部评分

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|RenPy中文空间 ( 苏ICP备17067825号|苏公网安备 32092302000068号 )

GMT+8, 2025-11-27 16:32 , Processed in 0.044246 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表