找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 25|回复: 0

[教程] renpy里的贪吃蛇!

[复制链接]
发表于 昨天 21:20 | 显示全部楼层 |阅读模式

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

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

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

Python部分,这里是纯Python代码:
[RenPy] 纯文本查看 复制代码

"""renpy
init -2 python:
"""

import random

class SnakeGame():

    def __init__(self, width=20, height=20, warp_h=False, warp_v=False):
        self.width = width if width >= 10 else 10
        self.height = height if height >= 10 else 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 = False
        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):
        while True:
            x = random.randint(0, self.width-1)
            y = random.randint(0, self.height-1)

            for (seg_x, seg_y) in self.snake:
                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 (x, y) == (seg_x, seg_y):
                    break
            else:
                self.food = (x, y)
                break

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

        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 True
        
        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 True
            
        return False
    
    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

        if self.check_collision(new_head_x, new_head_y):
            self.gameover = True

        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 s0 = Solid('#000000', xysize=(30, 30))
image s1 = Solid('#FFFFFF', xysize=(30, 30))
image s2 = Solid('#e7b40eff', xysize=(30, 30))
image s3 = Solid('#e70e0eff', xysize=(30, 30))

init python:

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

    def snake_board(st, at, snakegame):

        cells = []
        for row in snakegame.board:
            for cell in row:
                cells.append(f's{cell}')
                
        board = Grid(snakegame.width, snakegame.height, *cells)

        return board, 0.1

screen snakegame_screen(snakegame):

    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_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))

    if not (snakegame.gameover or snakegame.victory):
        timer 0.2 action Function(snakegame.move) repeat True
    else:
        frame:
            modal True
            align (0.5, 0.5)
            xysize (400, 300)

            vbox:
                align (0.5, 0.5)

                if snakegame.victory:
                    text 'you win!' xalign 0.5
                else:
                    text 'you lose' xalign 0.5
                null height 100
                hbox:
                    xalign 0.5

                    textbutton '重新开始' action Function(snakegame.reset_game)
                    textbutton '退出游戏' action Return()

label start:
    call screen snakegame_screen(snakegame)


然后就可以开始玩了,用方向键控制移动方向,之后也会出一期教程(和俄罗斯方块合成一期),如果有bug请及时反馈(
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-10-13 08:13 , Processed in 0.047883 second(s), 24 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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